165

在 Mockito文档javadocs中它说

建议使用 ArgumentCaptor 进行验证,但不要使用存根。

但我不明白 ArgumentCaptor 如何用于存根。有人可以解释上述声明并展示如何将 ArgumentCaptor 用于存根或提供一个链接来展示它是如何完成的吗?

4

3 回答 3

278

假设采用以下方法进行测试:

public boolean doSomething(SomeClass arg);

Mockito 文档说你不应该这种方式使用 captor:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

因为您可以在存根期间只使用匹配器:

when(someObject.doSomething(eq(expected))).thenReturn(true);

但验证是另一回事。如果您的测试需要确保使用特定参数调用此方法,请使用ArgumentCaptor它是为这种情况设计的:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));
于 2012-09-06T08:49:46.690 回答
2

假设地,如果搜索让您找到了这个问题,那么您可能想要这个:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

为什么?因为像我一样,您重视时间,而且您不会.equals仅仅为了单个测试场景而实施。

并且 99% 的测试会因 Mock 返回 null 而崩溃,在合理的设计中,您将null不惜一切代价避免返回,使用Optional或迁移到 Kotlin。这意味着verify不需要经常使用,而且 ArgumentCaptors 写起来太乏味了。

于 2019-11-26T17:01:34.673 回答
1

线

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

会做同样的事情

when(someObject.doSomething(Matchers.any())).thenReturn(true);

因此,当存根没有附加值时使用 argumentCaptor.capture()。使用 Matchers.any() 可以更好地显示实际发生的情况,因此更好的可读性。使用 argumentCaptor.capture(),您无法读取真正匹配的参数。当您有更多信息(预期参数的类)时,您可以使用更具体的匹配器来改进您的测试,而不是使用 any()。

还有一个问题:如果在存根时使用 argumentCaptor.capture(),则不清楚在验证后应该捕获多少个值。我们希望在验证期间捕获一个值,而不是在存根期间,因为此时还没有要捕获的值。那么参数捕获器在存根期间捕获方法捕获了什么?它捕获任何东西,因为还没有任何东西可以捕获。我认为这是未定义的行为,我不想使用未定义的行为。

于 2019-08-01T10:59:11.680 回答