Java 使用ArgumentCaptor验证模拟服务调用失败
在测试中,我使用模拟服务。我想检查服务是否使用其中一个参数的特定属性调用过一次。 然而,这个方法也被称为multiple times和其他参数,但我只对上面的一个调用感兴趣 我的意图是使用参数捕获器验证调用,以检查感兴趣的调用是否只被调用一次。 但是,这失败了,因为该方法被多次调用,并且随后检查参数captor 见下例:Java 使用ArgumentCaptor验证模拟服务调用失败,java,unit-testing,mockito,Java,Unit Testing,Mockito,在测试中,我使用模拟服务。我想检查服务是否使用其中一个参数的特定属性调用过一次。 然而,这个方法也被称为multiple times和其他参数,但我只对上面的一个调用感兴趣 我的意图是使用参数捕获器验证调用,以检查感兴趣的调用是否只被调用一次。 但是,这失败了,因为该方法被多次调用,并且随后检查参数captor 见下例: // service method void serviceMethod(String someString, MyType myType); // parameter ty
// service method
void serviceMethod(String someString, MyType myType);
// parameter type
class MyType {
private String id;
...
String getID() {
return id;
}
}
// test verification
ArgumentCaptor<MyType> paramCaptor = ArgumentCaptor.forClass(MyType.class);
// fail in verify
Mockito.verify(serviceMock, times(1)).serviceMethod(eq("someConstantValue"), paramCaptor);
assertEquals("123", paramCaptor.getValue().getID());
//服务方法
void serviceMethod(字符串someString,MyType MyType);
//参数类型
类MyType{
私有字符串id;
...
字符串getID(){
返回id;
}
}
//试验验证
ArgumentCaptor paramCaptor=ArgumentCaptor.forClass(MyType.class);
//验证失败
Mockito.verify(serviceMock,times(1)).serviceMethod(等式(“someConstantValue”),paramCaptor);
assertEquals(“123”,paramCaptor.getValue().getID());
编辑:
我不知道有什么方法可以完全满足你的要求
我喜欢@beatngu13答案
但是,另一种选择可能是结合使用atLeastOnce()和有序验证:
InOrder inOrder = inOrder(serviceMock);
inOrder.verify(serviceMock, atLeastOnce()).serviceMethod(eq("someConstantValue"), paramCaptor);
inOrder.verify(serviceMock).serviceMethod(eq("someConstantValue"), fakeParamOne);
inOrder.verify(serviceMock).serviceMethod(eq("someConstantValue"), fakeParamTwo);
assertEquals("123", paramCaptor.getValue().getID());
您可以在其中创建一个fakeParam对象,该对象与服务的其他调用的参数类似。编辑:
我不知道有什么方法可以完全满足你的要求
我喜欢@beatngu13答案
但是,另一种选择可能是结合使用atLeastOnce()和有序验证:
InOrder inOrder = inOrder(serviceMock);
inOrder.verify(serviceMock, atLeastOnce()).serviceMethod(eq("someConstantValue"), paramCaptor);
inOrder.verify(serviceMock).serviceMethod(eq("someConstantValue"), fakeParamOne);
inOrder.verify(serviceMock).serviceMethod(eq("someConstantValue"), fakeParamTwo);
assertEquals("123", paramCaptor.getValue().getID());
您可以在其中创建一个fakeParam对象,该对象与服务的其他调用的参数类似。您可以使用
atLeastOnce()
和getAllValues()
的组合来实现这一点:
或者更好:看看AssertJ。您可以使用
atLeastOnce()
和getAllValues()
的组合来实现这一点:
或者更好:看看AssertJ。我用hamcrest
匹配器解决了这个问题。匹配器在验证方法调用时检查参数值,而参数捕获器仅读取参数以供以后评估。
在这种情况下,具有未指定值的所有其他调用都会被过滤掉
static Matcher<MyType> typeIdIs(final String id) {
return new ArgumentMatcher<MyType>() {
@Override
public boolean matches(Object argument) {
return id.equals(((MyType)argument).getID());
}
};
}
Mockito.verify(serviceMock, times(1)).serviceMethod(eq("someConstantValue"), argThat(typeIdIs("123")));
静态匹配器类型id(最终字符串id){
返回新的ArgumentMatcher(){
@凌驾
公共布尔匹配(对象参数){
返回id.equals(((MyType)参数).getID());
}
};
}
Mockito.verify(serviceMock,times(1)).serviceMethod(eq(“someConstantValue”)、argThat(typeIdIs(“123”));
我用hamcrest匹配器解决了这个问题。匹配器在验证方法调用时检查参数值,而参数捕获器仅读取参数以供以后评估。
在这种情况下,具有未指定值的所有其他调用都会被过滤掉
static Matcher<MyType> typeIdIs(final String id) {
return new ArgumentMatcher<MyType>() {
@Override
public boolean matches(Object argument) {
return id.equals(((MyType)argument).getID());
}
};
}
Mockito.verify(serviceMock, times(1)).serviceMethod(eq("someConstantValue"), argThat(typeIdIs("123")));
静态匹配器类型id(最终字符串id){
返回新的ArgumentMatcher(){
@凌驾
公共布尔匹配(对象参数){
返回id.equals(((MyType)参数).getID());
}
};
}
Mockito.verify(serviceMock,times(1)).serviceMethod(eq(“someConstantValue”)、argThat(typeIdIs(“123”));
如果您将Mockito 2与Java 8一起使用,有一种简洁的方法可以做到这一点。看
该示例将重构为:
// service method
void serviceMethod(String someString, MyType myType);
// parameter type
class MyType {
private String id;
...
String getID() {
return id;
}
}
// using a Java 8 lambda to test the ID within a custom ArgumentMatcher
// passed to argThat
// Note: you don't need to say "times(1)" as this assumes 1 time
// times(1) in the argument captor version would also confuse things
// if you had other calls and you
// were just checking for whether a call like THIS had happens
Mockito.verify(serviceMock).serviceMethod(eq("someConstantValue"),
argThat(input -> input.getID().equals("123")));
lambda使它更干净,但您需要Java 8和Mockito 2。如果您将Mockito 2与Java 8一起使用,有一种简洁的方法可以做到这一点。看
该示例将重构为:
// service method
void serviceMethod(String someString, MyType myType);
// parameter type
class MyType {
private String id;
...
String getID() {
return id;
}
}
// using a Java 8 lambda to test the ID within a custom ArgumentMatcher
// passed to argThat
// Note: you don't need to say "times(1)" as this assumes 1 time
// times(1) in the argument captor version would also confuse things
// if you had other calls and you
// were just checking for whether a call like THIS had happens
Mockito.verify(serviceMock).serviceMethod(eq("someConstantValue"),
argThat(input -> input.getID().equals("123")));
lambda使它更干净,但您需要Java 8和Mockito 2。我想验证使用指定参数集只调用了一次服务。我想验证使用指定参数集只调用了一次服务。感谢您的支持。从未想过收集所有值以备以后检查。我用汉克雷斯特匹配器解决了这个问题。@Stefan不客气。添加了另一种方法以确保ID只出现一次。感谢您的支持。从未想过收集所有值以备以后检查。我用汉克雷斯特匹配器解决了这个问题。@Stefan不客气。添加了另一种方法来确保ID只出现一次。这是一种很好的方法。一般来说,论点捕获者是一种反模式。您应该能够通过verify使用参数解决这个问题。这是一个很好的方法。一般来说,论点捕获者是一种反模式。您应该能够通过验证的参数来解决这个问题。