unit-testing - 在 Spring Data Jpa 中测试缓存
问题描述
我有一个代码,我在其中应用缓存来获取对象。
服务:
@Service
class UserServiceImpl(
private val userRepository: UserRepository
) : UserService {
override fun create(userEntity: UserEntity): UserEntity = userRepository.save(userEntity)
.also { log.info("saved user {}", it) }
@Cacheable("users", key = "#id")
override fun get(id: Long): UserEntity = userRepository.findById(id)
.orElseThrow { EntityNotFoundException("User not found by id $id") }
.also { log.info("from db: received user {}", it) }
companion object {
private val log = KotlinLogging.logger { }
}
}
存储库:
@Repository
interface UserRepository : JpaRepository<UserEntity, Long> {
}
我已经用一个简单的控制器验证了缓存运行良好,但我无法通过测试来验证这一点。测试失败并出现错误:Verification failed: call 1 of 1: UserRepository(#1).findById(eq(1))). 3 matching calls found, but needs at least 1 and at most 1 calls
class UserServiceImplTest {
private val userRepository = mockkClass(UserRepository::class)
private val userService: UserService = UserServiceImpl(userRepository)
@Test
fun `get should use caching`() {
// given
val user = UserEntity(1, "Anna", "anna@gmail.com")
every { userRepository.save(user)} returns user
every { userRepository.findById(user.id!!) } returns Optional.of(user)
// when
userService.get(user.id!!)
userService.get(user.id!!)
userService.get(user.id!!)
// then
verify(exactly = 1) { userRepository.findById(user.id!!) }
}
}
也许我也需要以某种方式为测试启用缓存。或者我的测试写错了(这很可能)。如何编写测试以检查缓存是否正常工作?
解决方案
@Cacheable
将生成一个执行缓存的包装器方法。这个包装器将存在于 Spring 生成的代理上,因此在您自己创建时它不会发挥作用UserServiceImpl
。如果你想测试它,你需要让 Spring 上下文管理类,包括模拟。
例如,
@SpringBootTest
class UserServiceImplTest {
@MockBean
lateinit var userRepository: UserRepository
@Autowired
lateinit var userService: UserService
@Test
fun `get should use caching`() {
// given
val user = UserEntity(1, "Anna", "anna@gmail.com")
every { userRepository.save(user)} returns user
every { userRepository.findById(user.id!!) } returns Optional.of(user)
// when
userService.get(user.id!!)
userService.get(user.id!!)
userService.get(user.id!!)
// then
verify(exactly = 1) { userRepository.findById(user.id!!) }
}
}
推荐阅读
- mysql - 只允许在表中使用“main”标志的一行
- java - 如何防止 Firebase 用户登录错误的登录屏幕
- android - 如何正确取消 MediaPlayer.prepare()?
- java - 助焊剂阻止 Netty 启动
- facebook - Facebook Ads API 如何获取处于草稿状态的所有广告系列
- c# - Is there an easy way to hide/show Console.WriteLines during runtime?
- python - python:exchangelib:RHEL 6:GLIBC_2.14 问题
- ios - Nativescript 5 - 无法使用 xcode 进行分析
- c# - 需要在 Outlook ReportItem 上添加上下文菜单(就 Outlook 用户“阅读回执”而言)
- php - 如何在循环内使用 TCPDF 创建不同的 pdf 发票?