Reputation: 5682
I have been trying to mock the callback with no success. Here is an example code:
public class TestService {
private UtilService utilService;
private LoadingCache<String, String> cache= CacheBuilder.newBuilder()
.build(new CacheLoader<String, String>() {
public String load(String key) throws Exception {
System.out.println("key = " + key);
return getKey(key);
}
});
public String getkeyFromCache(String key) throws ExecutionException {
return cache.get(key);
}
@VisibleForTesting
public String getKey(String key) {
return utilService.getKey(key);
}
}
And a test case like this:
@RunWith(MockitoJUnitRunner.class)
public class TestServiceTest {
public static final String MYKEY = "Mykey";
@Spy
TestService testService=new TestService();
@Before
public void before() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCache() throws ExecutionException {
doReturn(MYKEY).when(testService).getKey(MYKEY);
String result=testService.getkeyFromCache(MYKEY);
String result2nd=testService.getkeyFromCache(MYKEY);
verify(testService,times(1)).getKey(MYKEY);
}
}
But it looks like it is not invoked
Wanted but not invoked:
testService.getKey("Mykey");
-> at utils.TestServiceTest.testCache(TestServiceTest.java:38)
However, there were other interactions with this mock:
-> at utils.TestServiceTest.testCache(TestServiceTest.java:36)
-> at utils.TestServiceTest.testCache(TestServiceTest.java:37)
at utils.TestServiceTest.testCache(TestServiceTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I want to test the cache functionality but not the UtilService one, so I want to mock it. I can't think of a way to use Answer or Captor for this test or I would have.
Upvotes: 2
Views: 2430
Reputation: 4987
Your issue is that you've created the spy yourself. So the callback will be tied to the real method. Allowing Mockito to deal with the object creation solves the issue. (I'm using mockito 1.10.19)
I've refactored your test code:
@RunWith(MockitoJUnitRunner.class)
public class TestServiceTest {
public static final String MYKEY = "Mykey";
@Spy
TestService testService;
@Test
public void testCache() throws ExecutionException {
doReturn(MYKEY).when(testService).getKey(MYKEY);
String result=testService.getkeyFromCache(MYKEY);
String result2nd=testService.getkeyFromCache(MYKEY);
verify(testService).getKey(MYKEY);
}
}
Note: As you are using the Mockito runner - you are not required to initialize Mockito yourself. Also times(1) is a default value for verifying the call.
Upvotes: 4
Reputation: 2085
When getKey() method is invoked inside the load() method, it is called inside TestService class, not through the mock-proxy. That's why
doReturn(MYKEY).when(testService).getKey(MYKEY);
doesn't work. However, you might and should mock UtilService and see that is accessed only once.
Upvotes: 1