首页 > 解决方案 > 在 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!!) }
    }
}

也许我也需要以某种方式为测试启用缓存。或者我的测试写错了(这很可能)。如何编写测试以检查缓存是否正常工作?

标签: unit-testingkotlincachingspring-data-jpaspring-test

解决方案


@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!!) }
    }
}

推荐阅读