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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:49:43  来源:igfitidea点击:

Mockito. Verify method arguments

javaunit-testingjunitmockito

提问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 eqmatcher 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 ArgumentMatcheris ArgumentCaptor.

的替代方法ArgumentMatcherArgumentCaptor

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

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


argThatplus 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 assertJasserts, but it's up to you which assertion framework to use.

现在测试说:Expected: Obj.description to contain 'KEY'. Was: 'Actual description'. 注意:我使用了assertJ断言,但使用哪个断言框架取决于您。



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


eqmatcher

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).*