I'm currently unable to use @Cacheble and @Mock/@InjectMocks in the same test class.
To be clear, for using the Mockito.verify(repository, times(1)) I need to @Mock the repository and use the annotation @InjectMock for the repository. Doing it, I can correctly verify the behave of my app, but the result of findById is not cached. In fact the manager.get(cacheName).get(key) will return null.
Instead, if i use the @Autowired annotation, the value is cached but the verify(repository, times(1)) return ZeroInteractions. I checked with the debugger and the behaviour is ok.
What i should do for have both the cache-store and the verify() working? Why is that happening?
[I'm using SpringBoot 2.1.3-release with Caffeine Cache Manager version 3.1.1]
This is the CacheManager class:
@Slf4j
@Configuration
@EnableCaching
public class CaffeineCacheConfig extends CachingConfigurerSupport {
@Bean("cacheManager")
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(generateCache());
return cacheManager;
}
}
This the Cache:
@Override
public CaffeineCache generateCache() {
return new CaffeineCache(name,
Caffeine.newBuilder()
.maximumSize(15)
.expireAfterWrite(60, TimeUnit.MINUTES)
.recordStats()
.build());
}
I have a service that im trying to cache which is like:
@Service
@CacheConfig(cacheNames = CacheLocations.APPLICATION_LEVEL)
@Transactional(readOnly = true)
public class ApplicationLevelService implements IApplicationLevelService
{
@Autowired
private ApplicationLevelRepository repository;
@Autowired
private CacheManager manager;
@Override
@Cacheable
public ApplicationLevel findById(int id)
{
return repository.findById(id);
}
}
Im trying to test it with this class (JUnit5):
@CacheConfig(cacheNames = {APPLICATION_LEVEL})
class ApplicationLevelCacheTest extends AbstractSpringTest
{
@InjectMocks
private ApplicationLevelService service;
@Mock
private ApplicationLevelRepository repository;
@Autowired
private CacheManager cacheManager;
@BeforeEach
void evictCache()
{
cacheManager.getCache(APPLICATION_LEVEL).clear();
}
@Nested
class TestApplicationLevelCache
{
@Test
@DisplayName("findAById() sets the resulting list in '" + CacheLocations.APPLICATION_LEVEL + "' cache")
void testApplicationLevelCaching_ApplicationLevelsAreCached_FindById()
{
when(repository.findById(anyInt())).thenReturn(Optional.of(new ApplicationLevel("mocked")));
assertNotNull(cacheManager.getCache(CacheLocations.APPLICATION_LEVEL));
var expected = service.findById(1);
verify(repository, times(1)).findById(anyInt());
assertNotNull(cacheManager.getCache(APPLICATION_LEVEL).get(1));
// should be cached
var actual = service.findById(1);
verifyZeroInteractions(repository);
assertEquals(expected, actual);
}
}
}
where AbstractSpringTest is just the class containing:
- @SpringJUnitConfig
- @SpringBootTest()
- @ActiveProfiles("test")