我现在正在学习Mockito,为了巩固我的学习,我正在做的一件事是将一个旧的JUnit测试从使用手工滚动的mock类转换为使用Mockito mock的测试。然而,我遇到了一个我不知道该如何处理的情况。
具体来说,我的测试单元构造了一个String
,它作为方法调用中的参数传递给模拟对象。我想测试String
是否构造正确。挑战在于String
的一部分是一个散列密钥,它是在内部生成的,每次调用时都会更改。一个可行的解决方案是在我的控制下生成哈希,并注入一个用于测试执行的伪生成器。然而,这是一项相当艰巨的工作。
我的旧的手动模拟类会存储传递给它的参数,我可以在测试中查询这些参数。这使我能够通过以下方式查询String
的开始和结束:
assertTrue(mockFtpClient.getFilePathAndName().startsWith("/data/inbound/XJSLGG."));
assertTrue(mockFtpClient.getFilePathAndName().endsWith(".pdf"));
这对我的品味来说已经足够了。所以我的问题是,是否可以使用Mockito来查询或获取传递给方法的参数,这样我就可以执行类似于上面的操作?
2011年6月24日更新:在这一点上,我已经排除了格农的回答。然而,从那以后,我发现了一种更适合我的东西,那就是ArgumentCaptor
。以下是它的工作原理:
ArgumentCaptor<String> fileNameArgument = ArgumentCaptor.forClass(String.class);
verify(mockFtpClient).putFileOnServer(fileNameArgument.capture());
assertTrue(fileNameArgument.getValue().startsWith(START_FILE_NAME) &&
fileNameArgument.getValue().endsWith(END_FILE_NAME));
Mockito的javadoc指出,当您有一次性的特定参数匹配需求时,ArgumentCaptor
通常是更好的选择,就像我在这里所做的那样。
基本上,您需要在Mockito中使用argThat(),这允许您将HamcrestMatcher作为验证参数。以下是用于对传入参数进行自定义断言的代码:
@Test
public void testname() throws Exception {
HashReceiver receiver = mock(HashReceiver.class);
receiver.set("hash");
verify(receiver).set(argThat(new HashMatcher()));
}
class HashMatcher extends BaseMatcher<String> {
@Override
public boolean matches(Object item) {
String hash = (String) item;
if (hash.startsWith("/data/inbound/XJSLGG.") && hash.endsWith(".pdf"))
return true;
return false;
}
}
// Mocked
class HashReceiver {
public void set(String hash) {
}
}
您可以改为使用通用匹配器,或者使用多个通用匹配器的组合。
看看这个问题的公认答案mockito-how-to-make-a-method-return--an-argument-was-passed-it它将向您展示如何掌握传递给mock方法调用的参数。