mockito的”getAllValues”在捕获的参数上替换了所有调用参数为最后一次调用。

huangapple go评论57阅读模式
英文:

mockito getAllValues on captured arguments replaces all invocation args with the last invocation

问题

以下是您的代码段的中文翻译部分:

在我的代码中,我有以下内容:

kiteOrderService.modifyOrder(params, profitBracketOrder.getOrder().orderId);

还有另一个地方的调用。通过调试,我已经验证了第一次调用的params.price为525,而第二次调用为475。但在测试代码中:

verify(mockKiteOrderService, times(2)).modifyOrder(orderParamsArgumentCaptor.capture(), eq("3"));
List<OrderParams> orderParamsCaptured = orderParamsArgumentCaptor.getAllValues();
assertThat(orderParamsCaptured.get(0).price).isEqualTo(525.0);
assertThat(orderParamsCaptured.get(1).price).isEqualTo(475.0);

orderParamsCaptured.get(0).price为475,这是两次调用都捕获的值。

在我的build.gradle中,我没有指定任何mockito依赖项,我有:

testImplementation ('org.junit.vintage:junit-vintage-engine'){
    exclude group: 'org.hamcrest', module :'hamcrest-core'
}

我也尝试添加:

testImplementation group: 'org.mockito', name: 'mockito-core', version: '5.3.1'

但没有任何区别。我不知道正在使用哪个mockito版本,我粘贴了我的build.gradle如下:

dependencies {
    implementation ('org.springframework.boot:spring-boot-starter-web')

    implementation group: 'com.google.truth', name: 'truth', version: '1.1.3'

    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation ('org.junit.vintage:junit-vintage-engine'){
        exclude group: 'org.hamcrest' , module :'hamcrest-core' 
    }
}

这可能是相关的。我的测试不是一个Spring Boot测试,而是一个普通的JUnit5单元测试,具有以下注解:

@ExtendWith(MockitoExtension.class)

希望这有所帮助。

英文:

In my code I have

kiteOrderService.modifyOrder(params, profitBracketOrder.getOrder().orderId);

and another invocation at another place. Via stepping through I have verified that the first invocation params.price is 525 and for the second it is 475. Yet in the test code

verify(mockKiteOrderService, times(2)).modifyOrder(orderParamsArgumentCaptor.capture(), eq(&quot;3&quot;));
List&lt;OrderParams&gt; orderParamsCaptured = orderParamsArgumentCaptor.getAllValues();
assertThat(orderParamsCaptured.get(0).price).isEqualTo(525.0); 
assertThat(orderParamsCaptured.get(1).price).isEqualTo(475.0);

orderParamsCaptured.get(0).price is 475 and this is the value captured for both invocations.

In my build.gradle I didn't have any mockito dependency specified, I have

testImplementation (&#39;org.junit.vintage:junit-vintage-engine&#39;){
	exclude group: &#39;org.hamcrest&#39; , module :&#39;hamcrest-core&#39; 
}

I have also tried adding

testImplementation group: &#39;org.mockito&#39;, name: &#39;mockito-core&#39;, version: &#39;5.3.1&#39;

but it didn't make any difference. I don't know which mockito version is getting used, I'm pasting my build.gradle below:

dependencies {
implementation (&#39;org.springframework.boot:spring-boot-starter-web&#39;)

implementation group: &#39;com.google.truth&#39;, name: &#39;truth&#39;, version: &#39;1.1.3&#39;

annotationProcessor &#39;org.springframework.boot:spring-boot-configuration-processor&#39;
testImplementation &#39;org.springframework.boot:spring-boot-starter-test&#39;
testImplementation (&#39;org.junit.vintage:junit-vintage-engine&#39;){
	exclude group: &#39;org.hamcrest&#39; , module :&#39;hamcrest-core&#39; 
}

}

that may be relevant. My test is not a spring boot test but a normal Junit5 unit test has has the annotation

@ExtendWith(MockitoExtension.class)

Any help is much appreciated.

答案1

得分: 0

你没有将价格传递给您的方法,并且价格没有被捕获。您传递了对“OrderParams”实例的引用。如果稍后修改此实例,则更改将反映在捕获的引用中。“ArgumentCaptor”不会奇迹般地复制其捕获的对象,它们只保留对它的引用。

这是一个简化的示例:

final Service svc = mock(Service.class);
final Params captor = ArgumentCaptor.forClass(Params.class);

final Params params = new Params();
params.setPrice(42);

svc.process(params);
verify(svc).process(captor.capture());

params.setPrice(1337); // 这会更改捕获的引用!

assertEquals(1337, captor.getValue().getPrice());

这与Mockito或ArgumentCaptors无关,而是与Java的工作方式有关。

必读:https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

英文:

You are not passing the price to your method and the price is not captured. You are passing a reference to an OrderParams instance. If you modify this instance later, the changes will be reflected in the captured reference. ArgumentCaptors do not magically copy their captured objects, they only keep a reference to it.

Here's a simplified example:

final Service svc = mock(Service.class);
final Params captor = ArgumentCaptor.forClass(Params.class);

final Params params = new Params();
params.setPrice(42);

svc.process(params);
verify(svc).process(captor.capture());

params.setPrice(1337); // this changes the captured reference!

assertEquals(1337, captor.getValue().getPrice());

This has nothing to do with Mockito or ArgumentCaptors, but the way Java works.

Must-read: https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

答案2

得分: 0

我发现为每个验证创建一个单独的ArgumentCaptor并以某种方式正确捕获了参数。

英文:

I found that creating a separate Argumentcaptor to use for each verification somehow captures the arguments correctly.

huangapple
  • 本文由 发表于 2023年5月7日 21:42:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定