Ho sviluppato un repository Spring Data, l’interfaccia MemberRepository
, che estende org.springframework.data.jpa.repository.JpaRepository
. MemberRepository
ha un metodo:
@Cacheable(CacheConfiguration.DATABASE_CACHE_NAME) Member findByEmail(String email);
Il risultato è memorizzato nella cache da Spring cache astraction (supportato da ConcurrentMapCache
).
Il problema che ho è che voglio scrivere un test di integrazione (contro hsqldb) che asserisce che il risultato viene recuperato da db la prima volta e dalla cache la seconda volta .
Inizialmente pensavo di prendere in giro l’infrastruttura jpa (gestore di quadro, ecc.) E in qualche modo affermare che il gestore di entity framework non viene chiamato la seconda volta ma sembra troppo difficile / ingombrante (vedere https://stackoverflow.com/a/23442457/536299 ).
Qualcuno può quindi fornire un consiglio su come testare il comportamento di caching di un metodo Spring Data Repository annotato con @Cacheable
?
Se si desidera testare un aspetto tecnico come la memorizzazione nella cache, non utilizzare affatto un database. È importante capire cosa vorresti testare qui. Volete assicurarvi che l’invocazione del metodo sia evitata per l’invocazione con gli stessi argomenti. Il repository che fronteggia un database è un aspetto completamente ortogonale di questo argomento.
Ecco cosa consiglierei:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class CachingIntegrationTest { // Your repository interface interface MyRepo extends Repository
Come puoi vedere, facciamo un po ‘di prove eccessive qui:
Ho provato a testare il comportamento della cache nella mia app utilizzando l’esempio di Oliver. Nel mio caso la mia cache è impostata sul livello di servizio e voglio verificare che il mio repo venga chiamato il numero giusto di volte. Sto usando spock mock invece di mockito. Ho passato un po ‘di tempo a cercare di capire perché i miei test stessero fallendo, fino a quando ho capito che i test eseguiti per primi stanno popolando la cache ed effettuando gli altri test. Dopo aver svuotato la cache per ogni test, hanno iniziato a comportarsi come previsto.
Ecco cosa ho finito con:
@ContextConfiguration class FooBarServiceCacheTest extends Specification { @TestConfiguration @EnableCaching static class Config { def mockFactory = new DetachedMockFactory() def fooBarRepository = mockFactory.Mock(FooBarRepository) @Bean CacheManager cacheManager() { new ConcurrentMapCacheManager(FOOBARS) } @Bean FooBarRepository fooBarRepository() { fooBarRepository } @Bean FooBarService getFooBarService() { new FooBarService(fooBarRepository) } } @Autowired @Subject FooBarService fooBarService @Autowired FooBarRepository fooBarRepository @Autowired CacheManager cacheManager def "setup"(){ // we want to start each test with an new cache cacheManager.getCache(FOOBARS).clear() } def "should return cached foobars "() { given: final foobars = [new FooBar(), new FooBar()] when: fooBarService.getFooBars() fooBarService.getFooBars() final fooBars = fooBarService.getFooBars() then: 1 * fooBarRepository.findAll() >> foobars } def "should return new foobars after clearing cache"() { given: final foobars = [new FooBar(), new FooBar()] when: fooBarService.getFooBars() fooBarService.clearCache() final fooBars = fooBarService.getFooBars() then: 2 * fooBarRepository.findAll() >> foobars } }