Caffeine Caching For Unit Testing

29 views Asked by At

I'm writing a unit test to verify my caching works as expected by reducing the number of calls to the database and using the cache itself only. I use caffeine caching for this purpose. The problem is, I can't fill the cache with value even though I call the method annotated with @Cacheable

I believe I don't have to share CacheProperties details because it's just a POJO class for reading application.yml file. It's working just fine. Could it be possible that I'm having this error because of the mock?

Repository Interface

interface MyRepo : Repository<Any, Any> {
    @Cacheable("myCache")
    fun findId(id: String): String
}

Cache Configuration

@EnableCaching
@Configuration
class CacheConfiguration(
    private val cacheProperties: CacheProperties,
) {
    @Bean
    fun cacheManager(): CacheManager {
        val caffeineCacheManager = CaffeineCacheManager()
        cacheProperties.caches.map { config ->
            caffeineCacheManager.registerCustomCache(
                config.name,
                buildCache(Duration.parse(config.ttl)),
            )
        }
        return caffeineCacheManager
    }

    private fun buildCache(ttl: Duration) =
        Caffeine.newBuilder().expireAfterWrite(ttl.toJavaDuration()).build<Any, Any>()
}

Unit Test

@SpringBootTest
@EnableConfigurationProperties
@ContextConfiguration(classes = [CacheConfiguration::class, CacheProperties::class])
class MyRepoTest {
    @Autowired
    lateinit var cacheManager: CacheManager

    private val myRepo = mockk<MyRepo>()

    @Test
    fun methodInvocationShouldBeCached() {
        val first = String()
        val second = String()

        every { myRepo.findId(any()) }.returnsMany(
            first,
            second,
        )

        // First invocation returns object returned by the method
        assertEquals(
            first,
            myRepo.findId("foo"),
        )

        // Verify cache was populated
        assertNotNull(cacheManager.getCache("myCache")!!["foo"])

        // Second invocation should return cached value, *not* second (as set up above)
        assertEquals(
            first,
            myRepo.findId("foo"),
        )

        // Verify repository method was invoked once
        verify(exactly = 1) { myRepo.findId("foo") }


        // Third invocation with different key is triggers the second invocation of the repo method
        assertEquals(
            myRepo.findId("bar"),
            second,
        )
    }
}
0

There are 0 answers