如何使用ArgumentCaptor进行存根?


Answers:


271

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

public boolean doSomething(SomeClass arg);

文档的Mockito说,你应该以这种方式使用的捕手:

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

感谢你的回答。我有个问题。在第三个代码块中,我们知道只有在将期望值传递给doSomething 时才返回true 。但是第二个代码块何时返回true?还是在这种情况下someObject总是为someMethod返回true?
无法

嗯,我相信您是说“但是什么时候在第三个代码块中返回true ?”。在第三个代码块中,我们只是不在乎返回值,而将其设为默认值。对于布尔值false,不是true
罗里克2012年

不,我将所有灰色背景块都算作代码块。包括第一个班轮。我指的是那行when(someObject.doSomething(argumentCaptor.capture()))。thenReturn(true);
无法

啊对不起 是的,在这种情况下,将始终返回true。
罗里克2012年

3
不确定“不与存根一起使用”的原因很简单。匹配器没有提供实际的预期参数(只是类型),尽管参数可能有误,但测试通过仍然可以。
dtc

0

线

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

会和

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

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

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


0

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

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.