mockito 验证与 ArgumentCaptor 的交互

新手上路,请多包涵

要检查与 mock 的交互次数,其中方法调用中的参数属于某种类型,可以这样做

mock.someMethod(new FirstClass());
mock.someMethod(new OtherClass());
verify(mock, times(1)).someMethod(isA(FirstClass.class));

这将通过对 isA 的调用,因为 someMethod 被调用两次,但只有一次带有参数 FirstClass

然而,这种模式在使用 ArgumentCaptor 时似乎是不可能的,即使 Captor 是为特定参数创建的 FirstClass

这行不通

mock.someMethod(new FirstClass());
mock.someMethod(new OtherClass());
ArgumentCaptor<FirstClass> captor = ArgumentCaptor.forClass(FirstClass.class);
verify(mock, times(1)).someMethod(captor.capture());

它说模拟被调用了不止一次。

有没有办法在捕获参数以供进一步检查的同时完成此验证?

原文由 Hilikus 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 658
2 个回答

我建议使用 Mockito 的 Hamcrest 集成为其编写一个好的、干净的匹配器。这允许您将验证与对传递的参数的详细检查结合起来:

 import static org.mockito.hamcrest.MockitoHamcrest.argThat;

verify(mock, times(1)).someMethod(argThat(personNamed("Bob")));

Matcher<Person> personNamed(final String name) {
    return new TypeSafeMatcher<Person>() {
        public boolean matchesSafely(Person item) {
            return name.equals(item.getName());
        }
        public void describeTo(Description description) {
            description.appendText("a Person named " + name);
        }
    };
}

匹配器通常会导致更具可读性的测试和更有用的测试失败消息。它们也往往是非常可重用的,您会发现自己构建了一个为测试您的项目而量身定制的库。最后,您还可以使用 JUnit 的 Assert.assertThat() 将它们用于正常测试断言,因此您可以双重使用它们。

原文由 Ryan Stewart 发布,翻译遵循 CC BY-SA 4.0 许可协议

引用文档:

请注意 ArgumentCaptor 不做任何类型检查,它只是为了避免在您的代码中强制转换。然而,这可能会在未来的主要版本中改变(可以添加类型检查)。

我不会为此使用 ArgumentCaptor 。此类捕获(字面意思)所有内容,尽管提供的类是 .forClass 参数。

为了实现你想要的,我建议使用 Mockito 的 Answer 接口拦截参数:

 private FirstClass lastArgument;

@Test
public void captureFirstClass() throws Exception {
    doAnswer(captureLastArgument()).when(mock).someMethod(anInstanceOfFirstClass());
    mock.someMethod(new FirstClass());
    mock.someMethod(new OtherClass());

    verify(mock, times(1)).someMethod(anInstanceOfFirstClass());
    //write your desired matchers against lastArgument object
}

private Answer<FirstClass> captureLastArgument() {
    return new Answer<FirstClass>() {
        @Override
        public FirstClass answer(InvocationOnMock invocation) throws Throwable {
            TestClass.this.lastArgument = (FirstClass) invocation.getArguments()[0];
            return null;
        }
    };
}

private static Object anInstanceOfFirstClass(){
    return Mockito.argThat(isA(FirstClass.class));
}

原文由 Marlon Bernardes 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题