我在谷歌上搜索了一下,但没有找到任何相关信息。我得到了这样的东西:

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();

现在,我想验证在runtestmethod()内部调用的mymethod(Object o)是否与对象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")));

我总是通过考试。我如何完成验证(如果可能的话)?

谢谢你!


当前回答

ArgumentMatcher的替代方案是ArgumentCaptor。

官方的例子:

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

捕捉器也可以使用@Captor注释定义:

@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
    //...
    verify(mock).doSomething(captor.capture());
    assertEquals("John", captor.getValue().getName());
}

其他回答

你是否尝试过使用相同的()匹配器?如:

verify(mockObj).someMethod(same(specificInstance));

我也有同样的问题。我尝试了eq()匹配器以及refEq()匹配器,但我总是有误报。当我使用相同的()匹配器时,当参数是不同的实例时测试失败,当参数是相同的实例时测试通过。

我用过Mockito。以这种方式验证

@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
    }
}
Verify(a).aFunc(eq(b))

在伪代码:

在实例中,一个名为aFunc的函数被调用。 验证这个调用得到了一个等于b的参数。

如果你不使用其他匹配器,你就不需要eq匹配器。 您使用的语法不正确—您的方法调用应该在.verify(mock)之外。您现在正在对方法调用的结果发起验证,而没有验证任何东西(没有进行方法调用)。因此所有测试都通过了。

你的代码应该是这样的:

Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");

argThat加上

这就是你验证论证失败的原因:

    verify(mock).mymethod(argThat(
                            x -> false ));

在哪里

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

argThat +断言

上面的测试将“说”Expected: lambda$…是:YourClass.toSting……如果在lambda中使用断言,你可以得到更具体的失败原因:

    verify(mock).mymethod(argThat( x -> {
      assertThat(x).isNotNull();
      assertThat(x.description).contains("KEY");
      return true;
    }));

❗️但是❗️:这只适用于

来电等待1次,或者 预期调用2+次,但验证器匹配的所有次数(返回true)。

如果被验证的方法调用2+次,mockito将所有被调用的组合传递给每个验证者。因此,mockito期望您的验证者对其中一个参数集无声地返回true,对其他有效调用则返回false(没有断言异常)。这种期望对于一个方法调用来说不是问题——它应该只返回true一次。

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

现在失败的测试会说:Expected: Obj.description包含'KEY'。是:“实际描述”。注意:我使用了assertJ断言,但是使用哪个断言框架取决于您。


直接的观点

Mokito使用equals()比较直接参数:

verify(mock).mymethod(expectedArg);
// NOTE:   ^ where the parentheses must be closed.

情商匹配器

不要对单个参数使用eq。使用前面提到的直接论证。 Mokito使用equals()比较直接参数 原因:eq将是SonarQube / sonarcloud违反:https://rules.sonarsource.com/java/tag/mockito/RSPEC-6068


有多个参数。

如果你使用argThat,所有的参数都必须匹配。例如,在不同的情况下,如果你有另一个带有2个参数的方法:

    verify(mock).mymethod2(eq("VALUE_1"), argThat((x)->false));
    // above is correct as eq() is also an argument matcher.

验证(模拟)。mymethod2(“VALUE_1 argThat ((x) - > false)); //以上不正确;将抛出一个异常,如第一个参数。没有参数匹配器。

地点:

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

最初问题失败的根本原因是括号放错了位置:

验证(mock.mymethod…这是错误的。右边是: 验证(模拟)。*