web-dev-qa-db-ja.com

Mockito:InvalidUseOfMatchersException

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

これを解決する方法についての入力はありますか?

108
devang

エラーメッセージは、ソリューションの概要をかなり明確に示しています。この線

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

すべての未加工値またはすべてのマッチャーのいずれかを使用する必要がある場合、1つの未加工値と1つのマッチャーを使用します。正しいバージョンは次のようになります

doNothing().when(cmd).dnsCheck(eq(Host), any(InetAddressFactory.class))
217
Ryan Stewart

私は長い間同じ問題を抱えていました。Matcherと値を混ぜる必要がしばしばありましたが、Mockitoでそれを実現することはできませんでした。最近まで!この投稿がかなり古いものであっても、それが誰かを助けることを願って、私はここに解決策を置きました。

MockitoでMatchers AND値を一緒に使用することは明らかに不可能ですが、変数の比較を受け入れるMatcherがあった場合はどうなりますか?それは問題を解決するでしょう...そして実際にあります: eq

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

この例では、「metas」は既存の値のリストです

26
sam

将来的には役に立つかもしれません:Mockitoは 'final'メソッドのモックをサポートしていません(現在)。同じInvalidUseOfMatchersExceptionをくれました。

私にとっての解決策は、メソッドの「最終」である必要のない部分を、アクセス可能な別のオーバーライド可能なメソッドに入れることでした。

ユースケースについて Mockito API を確認してください。

11
delucasvb

すべてのマッチャーを使用しているにもかかわらず、同じ問題が発生していました。

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

私がモックしようとしているメソッドは、静的メソッドのみを含むクラス(Xyz.classなど)の静的メソッドであり、次の行を書くのを忘れていたことを理解するのに少し時間がかかりました:

PowerMockito.mockStatic(Xyz.class);

それが問題の原因かもしれないので、他の人を助けるかもしれません。

0
S Kumar

私の場合、package-accessメソッドをモックしようとしたため、例外が発生しました。メソッドのアクセスレベルをpackageからprotectedに変更すると、例外はなくなりました。例えば。 Javaクラスの下、

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

メソッドString getName(String id)は、AT LEASTprotectedレベルである必要があります。これにより、モックメカニズム(サブクラス化)が機能します。

0
shizhen