【问题标题】:How to mock Google Guava cache builder?如何模拟 Google Guava 缓存生成器?
【发布时间】:2017-01-10 12:15:39
【问题描述】:
    @Component
    public class LibraryService {

        @Autowired
        private BookService bookService;

        private Cache<UUID, Book> bookCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterWrite(15, TimeUnit.MINUTES).build();

        public void someMethod(UUID bookId) {
          try {
            Book book = bookCache.get(bookId, () -> bookService.findBookByUuid(bookId));
            //some operations
          } catch (ExecutionException e) {
            throw new ProcessingFailureException("Failed to load cache value", e);
          }

         }

    }

我需要为这个类编写单元测试,以便我尝试如下模拟 Google Guava 缓存。

public class LibraryServiceTest {

    @InjectMocks
    private LibraryService service;

    @Mock
    private BookService bookService;

    @Mock
    private Cache<UUID, Book> bookCache;

    @Before
    public void initialize() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testMethod() throws ExecutionException {
        UUID bookId = UUID.randomUUID();
        Book book = new Book();

        when(bookCache.get(bookId, () -> bookService.findBookByUuid(bookId))).thenReturn(book);

        service.someMethod(bookId);
    }
}

我遇到了一些 NullPointer 异常。

com.google.common.util.concurrent.UncheckedExecutionException: java.lang.NullPointerException
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2203)
    at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
    at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4739)
Caused by: java.lang.NullPointerException

注意:我知道,我可以通过一些可测试的方式更改方法。在这种情况下,我不能这样做。

有什么办法可以模拟这本书的缓存吗?

【问题讨论】:

  • @InjectMocks 是否覆盖随机的、已分配的私有变量?您需要更多地考虑 IoC 术语 - CacheLibraryService依赖项 - 因此它应该被接口并注入。事实上,当您使用 Spring 时,我可以建议 Spring Cache - 支持 Guava Cache 作为后端,因此在功能上您的代码将是相同的。
  • 是的,我明白了,但问题是我目前无法更改实现。
  • 你能不能测试一下BookService 在第二次尝试加载本应缓存的书时不会被再次调用?这个类的编写方式,Cache 是一个私有的实现细节,不应该被测试。预期的行为应该是。另请参阅Ticker - 但如果您无法更改任何代码,那么您在这方面也很不走运。
  • 是的,我想是的。我可以跳过这个方法的单元测试,然后改变它并编写它。

标签: java unit-testing mocking mockito google-guava-cache


【解决方案1】:

如果您最好将 get 方法调用模拟为 next 以确保参数匹配,您的代码应该可以工作,这样您将获得预期的 book 实例作为结果。

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
...

public class LibraryServiceTest {
    ...

    @Test
    public void testMethod() throws ExecutionException {
        ...
        when(bookCache.get(eq(bookId), any(Callable.class))).thenReturn(book);
        ...
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 2016-07-10
    相关资源
    最近更新 更多