我的缓存配置如下;
@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)`
为什么会失败?难道不应该使用缓存吗?还是我的测试有误?
非常感谢任何帮助或指示! :)
verify(bookRepository, times(1)).getByIsbn(BOOK_ISBN); // FAILS HERE
当然这里失败了。因为在您已经调用此方法一次之前大约 4 行。在此检查中,您应该输入
times(2)
。下一次检查调用次数应该是 times(3)