vendredi 22 septembre 2017

Spring - delay time in tests without Thread.sleep()

I test service which use caching. I can test number of invocatins but I don't know how can I test "timeToLiveSeconds".

ehcache.xml:

<ehcache xmlns:xsi="http://ift.tt/ra1lAU"
         xsi:noNamespaceSchemaLocation="ehcache.xsd">
    <cache name="countries"
           maxEntriesLocalHeap="200"
           timeToLiveSeconds="120">
    </cache>
</ehcache>

@Component
@CacheConfig(cacheNames = "countries")
public class CountryService {

    private final CountryProvider countryProvider;

   @Autowired
    public CountryService(CountryProvider countryProvider) {
        this.countryProvider = countryProvider;
    }

    @Cacheable
    public Country findByCode(String code) {
        System.out.println("---> Loading country with code '" + code + "'");
        return countryProvider.veryExpensiveOperation(code);
    }

}

@Component
public class CountryProvider {

    public Country veryExpensiveOperation(String code) {
        try {
            System.out.println("Very expensive operation for code: " + code);
            Thread.sleep(10000);
        } catch (Exception e) {}

        return new Country(code);
    }
}

My test:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class CountryServiceTest {

    @Autowired
    private CountryService countryService;

    @Test
    public void name() throws Exception {
        // given
        final String code = "AB";
        final Country country = new Country(code);

        when(Config.countryProvider.veryExpensiveOperation(code))
                .thenReturn(country);

        // when
        final Country ab = countryService.findByCode(code);
        countryService.findByCode(code);
        countryService.findByCode(code);
        countryService.findByCode(code);

        // then
        assertThat(ab, equalTo(country));
        verify(Config.countryProvider, times(1))
                .veryExpensiveOperation(anyString());
    }

    @TestConfiguration
    @EnableCaching
    static class Config {

        @MockBean
        static CountryProvider countryProvider;

        @Bean
        @Primary
        CountryService countryService() {
            return new CountryService(countryProvider);
        }
    }

}

And now I want to test if numbers of invocations will be greater after specified cache live time:

@Test
        public void name() throws Exception {
            // given
            final String code = "AB";
            final Country country = new Country(code);

            when(Config.countryProvider.veryExpensiveOperation(code))
                    .thenReturn(country);

            // when
            final Country ab = countryService.findByCode(code);
            countryService.findByCode(code);
            countryService.findByCode(code);
            countryService.findByCode(code);
            Thread.sleep(120000);
            countryService.findByCode(code);


            // then
            assertThat(ab, equalTo(country));
            verify(Config.countryProvider, times(2))
                    .veryExpensiveOperation(anyString());
        }

But it doesn't work because I get 1 invocation and in generaly using Thread.sleep() is not good practice. Does exist any way to mock delay time? And how do you usually test caching?

Aucun commentaire:

Enregistrer un commentaire