【发布时间】:2017-11-07 00:28:59
【问题描述】:
我正在使用 Mockito 测试一种在内部进行网络调用并根据网络调用结果返回值的方法。该方法使用 SynchronousQueue 等待结果,结果由网络调用的回调设置:
HelperClass helperClassObject = new HelperClassObject();
...
public SomeResultCode methodWithNetworkCall() {
SynchronousQueue<SomeResultCode> resultQueue = new SynchronousQueue<>();
// some condition checking code
helperClassObject.makeNetworkCall(new GenericCallback() {
@Override
public void onSuccess(JSONObject response) {
resultQueue.offer(SomeResultCode.SUCCESS);
}
@Override
public void onFailure(VolleyError error) {
resultQueue.offer(SomeResultCode.FAILURE);
}
});
SomeResultCode resultCode = null;
try {
resultCode = resultQueue.poll(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}
return resultCode == null ? SomeResultCode.FAILURE : resultCode;
}
在我的一种单元测试方法中,我试图验证成功的网络调用是否返回了 SUCCESS。我尝试使用 ArgumentCaptor 和 doAnswer 来触发回调的 onSuccess。但是,该方法返回 FAILURE。我在 onSuccess 中放置了一个断点,看起来当我使用 ArgumentCaptor 方式时,onSuccess 是在轮询超时后触发的。当我使用 doAnswer 方式时,我看到在设置期间调用了 onSuccess (doAnswer.when),但在我实际调用该方法之后却没有。我做错了什么?
编辑 再次单步执行代码,看起来答案是从我正在测试的方法中调用的(即,当我在测试期间调用 testObject.methodWithNetworkCall 时),而不是在设置期间。所以它正在做它应该做的事情:响应 onSuccess。但它在调用 poll 之前用 onSuccess 响应。因此,问题似乎不在于答案和模拟通常不起作用/设置错误,而是使用 SynchronousQueue 进行测试时出现问题。
这是我的测试代码:
public class TestClassUnitTest {
TestClass sut;
HelperClass helperClassObject = mock(HelperClass.class);
@Before
public void setup() {
sut = new TestClass();
injectField(sut, "helperClassFieldName", helperClassObject);
}
public void injectField(Object testObject, String fieldName, T mockToInject) {
// some code using reflection to inject the mock object into the test object
}
@Test
public void testMethodWithNetworkCallWithCaptor() {
ArgumentCaptor<GenericCallback> captor = ArgumentCaptor.forClass(GenericCallback.class);
SomeResultCode result = sut.methodWithNetworkcall();
verify(helperClassObject, times(1)).makeNetworkCall(captor.capture());
captor.getValue().onSuccess(new JSONObject());
Assert.assertEquals(SomeResultCode.SUCCESS, result);
}
@Test
public void testMethodWithNetworkCallWithDoAnswer() {
doAnswer(new Answer(){
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
((GenericCallback)invocation.getArguments()[0]).onSuccess(new JSONObject());
return null;
}
}).when(helperClassObject).makeNetworkCall(any(GenericCallback.class));
SomeResultCode result = sut.methodWithNetworkcall();
Assert.assertEquals(SomeResultCode.SUCCESS, result);
}
}
【问题讨论】:
标签: java unit-testing callback mockito