Java 莫基托。验证方法参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3555472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito. Verify method arguments
提问by manolowar
I've googled about this, but didn't find anything relevant. I've got something like this:
我用谷歌搜索过这个,但没有找到任何相关的东西。我有这样的事情:
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);
Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();
Now, I want to verify that mymethod(Object o)
, which is called inside runtestmethod()
, was called with the Object o
, not any other. But I always pass the test, whatever I put on the verification, for example, with:
现在,我想验证mymethod(Object o)
被称为 inside 的runtestmethod()
是用 Object 调用的o
,而不是其他任何对象。但是我总是通过测试,无论我进行什么验证,例如:
Mockito.verify(mock.mymethod(Mockito.eq(obj)));
or
或者
Mockito.verify(mock.mymethod(Mockito.eq(null)));
or
或者
Mockito.verify(mock.mymethod(Mockito.eq("something_else")));
I always pass the test. How can I accomplish that verification (if possible)?
我总是通过考试。我如何完成该验证(如果可能)?
Thank you.
谢谢你。
回答by Bozho
- You don't need the
eq
matcher if you don't use other matchers. - You are not using the correct syntax - your method call should be outside the
.verify(mock)
. You are now initiating verification on the result of the method call, without verifying anything (not making a method call). Hence all tests are passing.
- 你并不需要
eq
匹配,如果你不使用其他的匹配。 - 您没有使用正确的语法 - 您的方法调用应该在
.verify(mock)
. 您现在正在启动对方法调用结果的验证,而不验证任何内容(不进行方法调用)。因此,所有测试都通过了。
You code should look like:
您的代码应如下所示:
Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");
回答by rit
Have you checked the equals method for the mockable class? If this one returns always true or you test the same instance against the same instance and the equal method is not overwritten (and therefor only checks against the references), then it returns true.
您是否检查过可模拟类的 equals 方法?如果这个总是返回 true 或者你针对同一个实例测试同一个实例并且 equal 方法没有被覆盖(因此只检查引用),那么它返回 true。
回答by Matthew Kirkley
Are you trying to do logical equality utilizing the object's .equals method? You can do this utilizing the argThat matcher that is included in Mockito
您是否尝试使用对象的 .equals 方法进行逻辑相等?您可以使用 Mockito 中包含的 argThat 匹配器来执行此操作
import static org.mockito.Matchers.argThat
Next you can implement your own argument matcher that will defer to each objects .equals method
接下来,您可以实现自己的参数匹配器,该匹配器将遵循每个对象的 .equals 方法
private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
T thisObject;
public ObjectEqualityArgumentMatcher(T thisObject) {
this.thisObject = thisObject;
}
@Override
public boolean matches(Object argument) {
return thisObject.equals(argument);
}
}
Now using your code you can update it to read...
现在使用您的代码,您可以更新它以阅读...
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);
Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();
verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));
If you are just going for EXACT equality (same object in memory), just do
如果你只是想要完全相等(内存中的同一个对象),那就做
verify(mock).mymethod(obj);
This will verify it was called once.
这将验证它是否被调用过一次。
回答by cbbcloud
Have you tried it with the same() matcher? As in:
您是否尝试过使用 same() 匹配器?如:
verify(mockObj).someMethod(same(specificInstance));
I had the same problem. I tried it with the eq() matcher as well as the refEq() matcher but I always had false positives. When I used the same() matcher, the test failed when the arguments were different instances and passed once the arguments were the same instance.
我有同样的问题。我用 eq() 匹配器和 refEq() 匹配器尝试过,但我总是有误报。当我使用 same() 匹配器时,当参数是不同的实例时测试失败,并且一旦参数是相同的实例就通过了。
回答by eugene82
An alternative to ArgumentMatcher
is ArgumentCaptor
.
的替代方法ArgumentMatcher
是ArgumentCaptor
。
Official example:
官方示例:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());
A captor can also be defined using the @Captorannotation:
还可以使用@Captor注释定义捕获器:
@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
//...
verify(mock).doSomething(captor.capture());
assertEquals("John", captor.getValue().getName());
}
回答by sendon1982
You can also use TypeSafeDiagnosingMatcher
您还可以使用 TypeSafeDiagnosingMatcher
private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {
StringBuilder text = new StringBuilder(500);
@Override
protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
String productCode = req.getPackageIds().iterator().next().getValue();
if (productCode.equals(request.getSupplierProductCode())) {
text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
return true;
}
text.append(req.toString());
return false;
}
@Override
public void describeTo(Description d) {
d.appendText(text.toString());
}
};
}
Then verify that invocation:
然后验证该调用:
Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
回答by Nils Renaud
The other method is to use the org.mockito.internal.matchers.Equals.Equals method instead of redefining one :
另一种方法是使用 org.mockito.internal.matchers.Equals.Equals 方法而不是重新定义一个:
verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));
回答by Free-Minded
I have used Mockito.verify in this way
我以这种方式使用了 Mockito.verify
@UnitTest
public class JUnitServiceTest
{
@Mock
private MyCustomService myCustomService;
@Test
public void testVerifyMethod()
{
Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); // no other method called except this
}
}
回答by epox
argThat
plus lambda
argThat
加上拉姆达
that is how you can fail your argument verification:
这就是您无法通过参数验证的方式:
verify(mock).mymethod(argThat(
(x)->false
));
where
在哪里
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
argThat
plus asserts
argThat
加断言
the above test will "say" Expected: lambda$... Was: YourClass.toSting...
. You can get a more specific cause of the failure if to use asserts in the the lambda:
上面的测试会“说” Expected: lambda$... Was: YourClass.toSting...
。如果在 lambda 中使用断言,您可以获得更具体的失败原因:
verify(mock).mymethod(argThat( x -> {
assertThat(x).isNotNull();
assertThat(x.description).contains("KEY");
return true;
}));
where
在哪里
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
Now the test says: Expected: Obj.description to contain 'KEY'. Was: 'Actual description'
. NOTE: I used assertJ
asserts, but it's up to you which assertion framework to use.
现在测试说:Expected: Obj.description to contain 'KEY'. Was: 'Actual description'
. 注意:我使用了assertJ
断言,但使用哪个断言框架取决于您。
argThat
with multiple arguments.
argThat
带有多个参数。
If you use argThat
, all argumentsmust be provided with matches. E.g.:
如果使用argThat
,则必须为所有参数提供匹配项。例如:
verify(mock).mymethod(eq("VALUE_1"), argThat((x)->false));
// above is correct as eq() is also an argument matcher.
verify(mock).mymethod("VALUE_1", argThat((x)->false));
// above is incorrect; an exceptoin will be thrown, as the fist arg. is given without an argument matcher.
verify(mock).mymethod("VALUE_1", argThat((x)->false));
// above is incorrect; an exceptoin will be thrown, as the fist arg. is given without an argument matcher.
where:
在哪里:
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
eq
matcher
eq
匹配器
the easiest way to check if the argument is equal:
检查参数是否相等的最简单方法:
verify(mock).mymethod(eq(expectedValue));
// NOTE: ^ where the parentheses must be closed.
direct argument
直接论证
if comparison by ref is acceptable, then go on with:
如果通过 ref 进行比较是可以接受的,那么继续:
verify(mock).mymethod(expectedArg);
// NOTE: ^ where the parentheses must be closed.
THE ROOT CAUSE of original question failure was the wrong place of the paranthes: verify(mock.mymethod...
. That was wrong. The right would be: verify(mock).*
原始问题失败的根本原因是括号的错误位置:verify(mock.mymethod...
。那是错误的。正确的是:verify(mock).*