web-dev-qa-db-fra.com

Comment tester @Cacheable?

J'ai du mal à tester @Cacheable dans un test d'intégration Spring Boot. C'est mon deuxième jour pour apprendre à faire des tests d'intégration et tous les exemples que j'ai trouvés utilisent des versions plus anciennes. J'ai également vu un exemple de assetEquals("some value", is()) mais rien avec une instruction d'importation pour savoir à quelle dépendance "appartient" appartient. Le test échoue à la seconde

Ceci est mon test d'intégration ....

@RunWith(SpringRunner.class)
@DataJpaTest // used for other methods
@SpringBootTest(classes = TestApplication.class)
@SqlGroup({
        @Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD,
                scripts = "classpath:data/Setting.sql") })
public class SettingRepositoryIT {

    @Mock
    private SettingRepository settingRepository;

    @Autowired
    private Cache applicationCache;


    @Test
    public void testCachedMethodInvocation() {
        List<Setting> firstList = new ArrayList<>();
        Setting settingOne = new Setting();
        settingOne.setKey("first");
        settingOne.setValue("method invocation");
        firstList.add(settingOne);

        List<Setting> secondList = new ArrayList<>();
        Setting settingTwo = new Setting();
        settingTwo.setKey("second");
        settingTwo.setValue("method invocation");
        secondList.add(settingTwo);

        // Set up the mock to return *different* objects for the first and second call
        Mockito.when(settingRepository.findAllFeaturedFragrances()).thenReturn(firstList, secondList);

        // First invocation returns object returned by the method
        List<Setting> result = settingRepository.findAllFeaturedFragrances();
        assertEquals("first", result.get(0).getKey());

        // Second invocation should return cached value, *not* second (as set up above)
        List<Setting> resultTwo = settingRepository.findAllFeaturedFragrances();
        assertEquals("first", resultTwo.get(0).getKey()); // test fails here as the actual is "second."

        // Verify repository method was invoked once
        Mockito.verify(settingRepository, Mockito.times(1)).findAllFeaturedFragrances();
        assertNotNull(applicationCache.get("findAllFeaturedFragrances"));

        // Third invocation with different key is triggers the second invocation of the repo method
        List<Setting> resultThree = settingRepository.findAllFeaturedFragrances();
        assertEquals(resultThree.get(0).getKey(), "second");
    }
}

ApplicationContext, composants, entités, référentiels et couche de service pour les tests. La raison pour laquelle je le fais de cette façon est que ce module maven est utilisé dans d'autres modules comme dépendance.

@ComponentScan({ "com.persistence_common.config", "com.persistence_common.services" })
@EntityScan(basePackages = { "com.persistence_common.entities" })
@EnableJpaRepositories(basePackages = { "com.persistence_common.repositories" })
@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Configuration du cache ....

@Configuration
@EnableCaching
public class CacheConfig {

    public static final String APPLICATION_CACHE = "applicationCache";

    @Bean
    public FilterRegistrationBean registerOpenSessionInViewFilterBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter();
        registrationBean.setFilter(filter);
        registrationBean.setOrder(5);
        return registrationBean;
    }


    @Bean
    public Cache applicationCache() {
        return new GuavaCache(APPLICATION_CACHE, CacheBuilder.newBuilder()
                .expireAfterWrite(30, TimeUnit.DAYS)
                .build());
    }
}

Le dépôt sous test ....

public interface SettingRepository extends JpaRepository<Setting, Integer> {

    @Query(nativeQuery = true, value = "SELECT * FROM Setting WHERE name = 'featured_fragrance'")
    @Cacheable(value = CacheConfig.APPLICATION_CACHE, key = "#root.methodName")
    List<Setting> findAllFeaturedFragrances();
}
11
Grim

Dans mon cas, je voulais valider l'expression dans l'expression sauf dans l'annotation @Cacheable, donc je pense que c'est parfaitement logique et je ne teste pas le code de Spring.

J'ai réussi à le tester sans utiliser Spring Boot, il s'agit donc d'un simple test Spring:

@RunWith(SpringRunner.class)
@ContextConfiguration
public class MyTest {

    @Configuration
    @EnableCaching
    static class Config {

        @Bean
        public MyCacheableInterface myCacheableInterface() {
            return (authorization) -> createTestResult();
        }

        @Bean
        public CacheManager cacheManager() {
            return new ConcurrentMapCacheManager("myObject");
        }
    }

    @Autowired
    private MyCacheableInterface myCacheableInterface;

Dans MyCacheableInterface, j'ai l'annotation suivante:

public interface MyCacheableInterface {
    @Cacheable(value = "myObject", unless = "#result.?[Retorno.getSucesso() != 'S'].size() == #result.size()")
    List<MyObject> businessMethod(String authorization);
}