166

我有一个执行 DNS 检查的命令行工具。如果 DNS 检查成功,该命令将继续执行其他任务。我正在尝试使用 Mockito 为此编写单元测试。这是我的代码:

public class Command() {
    // ....
    void runCommand() {
        // ..
        dnsCheck(hostname, new InetAddressFactory());
        // ..
        // do other stuff after dnsCheck
    }

    void dnsCheck(String hostname, InetAddressFactory factory) {
        // calls to verify hostname
    }
}

我正在使用 InetAddressFactory 来模拟InetAddress该类的静态实现。这是工厂的代码:

public class InetAddressFactory {
    public InetAddress getByName(String host) throws UnknownHostException {
        return InetAddress.getByName(host);
    }
}

这是我的单元测试用例:

@RunWith(MockitoJUnitRunner.class)
public class CmdTest {

    // many functional tests for dnsCheck

    // here's the piece of code that is failing
    // in this test I want to test the rest of the code (i.e. after dnsCheck)
    @Test
    void testPostDnsCheck() {
        final Cmd cmd = spy(new Cmd());

        // this line does not work, and it throws the exception below:
        // tried using (InetAddressFactory) anyObject()
        doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class));
        cmd.runCommand();
    }
}

运行testPostDnsCheck()测试异常:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

关于如何解决这个问题的任何意见?

4

7 回答 7

336

错误消息概述了解决方案。线

doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class))

当需要使用所有原始值或所有匹配器时,使用一个原始值和一个匹配器。正确的版本可能是

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))
于 2013-02-13T03:03:31.933 回答
38

很长一段时间以来我都遇到了同样的问题,我经常需要混合匹配器和值,而我从来没有用 Mockito 做到这一点......直到最近!我将解决方案放在这里,希望即使这篇文章已经很老了,它也会对某人有所帮助。

在 Mockito 中显然不可能同时使用 Matchers 和值,但是如果有一个 Matcher 接受比较变量怎么办?这将解决问题......事实上有:eq

when(recommendedAccessor.searchRecommendedHolidaysProduct(eq(metas), any(List.class), any(HotelsBoardBasisType.class), any(Config.class)))
            .thenReturn(recommendedResults);

在此示例中,“metas”是现有的值列表

于 2015-06-01T12:55:17.980 回答
20

它可能对将来的某个人有所帮助:Mockito 不支持模拟“最终”方法(现在)。它给了我同样的InvalidUseOfMatchersException

对我来说,解决方案是将不需要“最终”的方法部分放在单独的、可访问的和可覆盖的方法中。

查看适用于您的用例的Mockito API

于 2017-01-26T13:40:18.847 回答
1

就我而言,引发异常是因为我试图模拟一个package-access方法。当我将方法访问级别从package更改protected为异常时,异常消失了。例如在Java类下面,

public class Foo {
    String getName(String id) {
        return mMap.get(id);
    }
}

该方法String getName(String id)必须是至少 protected级别,以便模拟机制(子类)可以工作。

于 2019-08-01T05:36:23.863 回答
0

可能对某人有帮助。模拟方法必须是模拟,用mock(MyService.class)

于 2021-01-25T11:22:15.173 回答
0

尽管使用了所有匹配器,但我遇到了同样的问题:

"org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
1 matchers expected, 3 recorded:"

我花了一点时间才发现我试图模拟的方法是一个类的静态方法(比如 Xyz.class),它只包含静态方法,我忘了写下一行:

PowerMockito.mockStatic(Xyz.class);

可能它会帮助其他人,因为它也可能是问题的原因。

于 2018-06-22T09:07:14.097 回答
-1

Do not use Mockito.anyXXXX(). Directly pass the value to the method parameter of same type. Example:

A expected = new A(10);

String firstId = "10w";
String secondId = "20s";
String product = "Test";
String type = "type2";
Mockito.when(service.getTestData(firstId, secondId, product,type)).thenReturn(expected);

public class A{
   int a ;
   public A(int a) {
      this.a = a;
   }
}
于 2020-10-15T15:55:43.870 回答