测试 Spring Boot 缓存(咖啡因)

问题描述 投票:0回答:1

我的缓存配置如下;

@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager(Ticker ticker) {
        CaffeineCache bookCache = buildCache("books", ticker, 30);
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Collections.singletonList(bookCache));
        return cacheManager;
    }

    private CaffeineCache buildCache(String name, Ticker ticker, int minutesToExpire) {
        return new CaffeineCache(name, Caffeine.newBuilder()
                .expireAfterWrite(minutesToExpire, TimeUnit.MINUTES)
                .maximumSize(100)
                .ticker(ticker)
                .build());
    }

    @Bean
    public Ticker ticker() {
        return Ticker.systemTicker();
    }
}

我想测试的服务:

@Service
public class TestServiceImpl implements TestService {

    private final BookRepository bookRepository; // interface

    @Autowired
    public TestServiceImpl(final BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @Override
    public Book getByIsbn(String isbn) {
        return bookRepository.getByIsbn(isbn);
    }
}

存储库中所需的方法用

@Cacheable("books")
注释。

@Override
@Cacheable("books")
public Book getByIsbn(String isbn) {
    LOGGER.info("Fetching Book...");
    simulateSlowService(); //  Wait for 5 secs
    return new Book(isbn, "Some book");
}

我需要编写一个测试来显示缓存的工作原理。因此,我在测试中创建了另一个

ticker
bean,以覆盖
CacheConfiguration
中现有的 bean。代码;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestServiceTests {

    private static final String BOOK_ISBN = "isbn-8442";

    @SpyBean
    private BookRepository bookRepository;

    @Autowired
    private TestService testService;

    @Configuration
    @Import(SpringBootCacheApplication.class)
    public static class TestConfiguration {

        //testCompile('com.google.guava:guava-testlib:23.6-jre')
        static FakeTicker fakeTicker = new FakeTicker();

        @Bean
        public Ticker ticker() {
            return fakeTicker::read;
        }
    }

    @Before
    public void setUp() {
        Book book = fakeBook();
        doReturn(book)
                .when(bookRepository)
                .getByIsbn(BOOK_ISBN);
    }

    private Book fakeBook() {
        return new Book(BOOK_ISBN, "Mock Book");
    }

    @Test
    public void shouldUseCache() {
        // Start At 0 Minutes
        testService.getByIsbn(BOOK_ISBN);
        verify(bookRepository, times(1)).getByIsbn(BOOK_ISBN);

        // After 5 minutes from start, it should use cached object
        TestConfiguration.fakeTicker.advance(5, TimeUnit.MINUTES);
        testService.getByIsbn(BOOK_ISBN);
        verify(bookRepository, times(1)).getByIsbn(BOOK_ISBN); // FAILS HERE

        // After 35 Minutes from start, it should call the method again
        TestConfiguration.fakeTicker.advance(30, TimeUnit.MINUTES);
        testService.getByIsbn(BOOK_ISBN);
        verify(bookRepository, times(2)).getByIsbn(BOOK_ISBN);
    }
}

但是在标有

//FAILS HERE
并带有消息的行处失败;

org.mockito.exceptions.verification.TooManyActualInvocations:
simpleBookRepository.getByIsbn("isbn-8442");
Wanted 1 time:
-> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
But was 2 times. Undesired invocation:
-> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)`

为什么会失败?难道不应该使用缓存吗?还是我的测试有误?

非常感谢任何帮助或指示! :)

spring-boot spring-test caffeine-cache
1个回答
0
投票
verify(bookRepository, times(1)).getByIsbn(BOOK_ISBN); // FAILS HERE

当然这里失败了。因为在您已经调用此方法一次之前大约 4 行。在此检查中,您应该输入

times(2)
。下一次检查调用次数应该是
times(3)

© www.soinside.com 2019 - 2024. All rights reserved.