我正在编写selenium测试并使用mockito验证服务器行为。具体来说,当单击一个按钮时,我想确保页面控制器调用我所模拟的依赖项上的特定方法。
因为它是一个selenium测试,我需要等待在另一个线程中调用mock,所以我正在使用mockito timeout。
verify(myMock, timeout(5000).times(1)).myMethod("expectedArg");
我遇到的麻烦是多次调用myMethod ...而不是等待与预期参数匹配的调用,超时只等待第一次调用。 如果我使用Thread.sleep(50000)而不是超时(50000),它会按预期工作......但这很脏,所以我希望避免它。
如何使用预期输入等待myMethod调用?
答案 0 :(得分:17)
如果您能够设置一定数量的预期来电,可以使用ArgumentCaptor
来完成:
import static org.hamcrest.CoreMatchers.hasItem;
@Captor ArgumentCaptor<String> arg;
@Before
public void setUp() throws Exception {
// init the @Captor
initMocks(this);
}
@Test
public void testWithTimeoutCallOrderDoesntMatter() throws Exception {
// there must be exactly 99 calls
verify(myMock, timeout(5000).times(99)).myMethod(arg.capture());
assertThat(arg.getAllValues(), hasItem("expectedArg"));
}
另一种方法是指定要验证的所有预期值,但这些值需要按照调用它们的确切顺序提供。与上述解决方案的不同之处在于,即使使用一些未经验证的参数另外调用mock,这也不会失败。换句话说,无需知道总调用次数。代码示例:
@Test
public void testWithTimeoutFollowingCallsDoNotMatter() throws Exception {
// the order until expected arg is specific
verify(callback, timeout(5000)).call("firstExpectedArg");
verify(callback, timeout(5000)).call("expectedArg");
// no need to tell more, if additional calls come after the expected arg
// verify(callback, timeout(5000)).call("randomArg");
}
答案 1 :(得分:15)
这不是一个超级干净的解决方案,但你可以这样做(XX
是这里假定的返回类型):
final CountDownLatch latch = new CountDownLatch(1);
doReturn(new Answer<XX>()
{
@Override
public XX answer(InvocationOnMock invocation)
{
latch.countDown();
return someInstanceOfXX;
}
}
).when(myMock).myMethod("expectedArg");
然后,为了测试方法是否被调用,请执行:
try {
assertTrue(latch.await(5L, TimeUnit.SECONDS));
} catch (InterruptedException e) {
// Urgh... Failed. Deal with it and:
Thread.currentThread.interrupt();
}