如何使用ArgumentCaptor进行存根?

时间:2012-09-06 08:23:30

标签: java unit-testing junit mockito

在Mockito documentationjavadocs中,它说

  

建议使用带验证的ArgumentCaptor,但不要使用存根。

但我不明白ArgumentCaptor如何用于存根。有人可以解释上面的陈述并说明ArgumentCaptor如何用于存根或提供一个链接来说明如何完成它?

3 个答案:

答案 0 :(得分:249)

假设要测试以下方法:

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));

答案 1 :(得分:0)

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

将与

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

因此,在存根时没有附加值时使用argumentsCaptor.capture()。使用Matchers.any()可以更好地显示实际情况,因此可读性更好。 使用argumentsCaptor.capture(),您无法读取真正匹配的参数。 并且,除了使用any()之外,您还可以在拥有更多信息(预期参数的类)时使用更具体的匹配器来改善测试。

另一个问题: 如果在存根时使用argumentsCaptor.capture(),则不清楚您希望在验证后捕获多少个值。我们希望在验证过程中而不是在存根过程中捕获一个值,因为那时还没有捕获值。那么,参数捕捉器捕获方法在存根过程中捕获了什么?还是没有捕获到任何东西? 我没有这个问题的答案。我认为这是未定义的行为,并且我不想使用未定义的行为。

答案 2 :(得分:0)

假设地,如果搜索使您陷入了这个问题,那么您可能想要这个:

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

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

99%的测试因Mock返回空值而崩溃,在合理的设计中,您将不计一切代价避免返回null,使用Optional或搬到Kotlin。这意味着verify不需要经常使用,并且ArgumentCaptors太繁琐而无法编写。