Search code examples
javaunit-testingmockingmockitogoogle-guava-cache

How to mock Google Guava cache builder?


    @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);
          }

         }

    }

I need to write unit test for this class so that I tried to mock the Google Guava cache as following.

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);
    }
}

I got some NullPointer Exception.

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

Note: I know, I can change the method some testable way. In this case I couldn't do that.

Is there any way to mock this book cache?


Solution

  • Your code should work if you better mock the get method call as next to ensure arguments match such that you will get the expected book instance as result.

    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);
            ...
        }
    }