简体   繁体   English

如何使用 ArgumentCaptor 进行存根?

[英]How to use ArgumentCaptor for stubbing?

In Mockito documentation and javadocs it says在 Mockito 文档javadocs 中,它说

It is recommended to use ArgumentCaptor with verification but not with stubbing.建议将 ArgumentCaptor 与验证一起使用,但不要与存根一起使用。

but I don't understand how ArgumentCaptor can be used for stubbing.但我不明白 ArgumentCaptor 如何用于存根。 Can someone explain the above statement and show how ArgumentCaptor can be used for stubbing or provide a link that shows how it can be done?有人可以解释上面的语句并展示 ArgumentCaptor 如何用于存根或提供一个链接来展示它是如何完成的吗?

Assuming the following method to test:假设采用以下方法进行测试:

public boolean doSomething(SomeClass arg);

Mockito documentation says that you should not use captor in this way:文档的Mockito说,你应该以这种方式使用的捕手:

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

Because you can just use matcher during stubbing:因为您可以在存根期间使用匹配器:

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

But verification is a different story.但验证是另一回事。 If your test needs to ensure that this method was called with a specific argument, use ArgumentCaptor and this is the case for which it is designed:如果您的测试需要确保使用特定参数调用此方法,请使用ArgumentCaptor ,这是它设计的情况:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));

Hypothetically, if search landed you on this question then you probably want this:假设,如果搜索让你找到这个问题,那么你可能想要这个:

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

Why?为什么? Because like me you value time and you are not going to implement .equals just for the sake of the single test scenario.因为像我一样,你很珍惜时间,你不会仅仅为了单一的测试场景而实现.equals

And 99 % of tests fall apart with null returned from Mock and in a reasonable design you would avoid return null at all costs, use Optional or move to Kotlin.并且 99% 的测试会因 Mock 返回的 null 而失败,在合理的设计中,您将不惜一切代价避免返回null ,使用Optional或转向 Kotlin。 This implies that verify does not need to be used that often and ArgumentCaptors are just too tedious to write.这意味着不需要经常使用verify并且 ArgumentCaptors 编写起来太乏味了。

The line线

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

would do the same as会做同样的事情

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

So, using argumentCaptor.capture() when stubbing has no added value.因此,当存根没有附加值时使用argumentCaptor.capture()。 Using Matchers.any() shows better what really happens and therefor is better for readability.使用 Matchers.any() 可以更好地显示真正发生的事情,因此可读性更好。 With argumentCaptor.capture(), you can't read what arguments are really matched.使用argumentCaptor.capture(),您无法读取真正匹配的参数。 And instead of using any(), you can use more specific matchers when you have more information (class of the expected argument), to improve your test.而不是使用 any(),当您有更多信息(预期参数的类)时,您可以使用更具体的匹配器来改进您的测试。

And another problem: If using argumentCaptor.capture() when stubbing it becomes unclear how many values you should expect to be captured after verification.还有一个问题:如果在存根时使用 argumentCaptor.capture() ,则不清楚在验证后应该捕获多少个值。 We want to capture a value during verification, not during stubbing because at that point there is no value to capture yet.我们希望在验证期间捕获一个值,而不是在存根期间,因为此时还没有要捕获的值。 So what does the argument captors capture method capture during stubbing?那么参数捕获器捕获方法在存根期间捕获了什么? It capture anything because there is nothing to be captured yet.它捕获任何东西,因为还没有什么可捕获的。 I consider it to be undefined behavior and I don't want to use undefined behavior.我认为这是未定义的行为,我不想使用未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM