2013-02-13 1 views
74

Ich habe ein Befehlszeilentool, das eine DNS-Überprüfung durchführt. Wenn die DNS-Prüfung erfolgreich ist, fährt der Befehl mit weiteren Aufgaben fort. Ich versuche mit Mockito Unit-Tests zu schreiben. Hier ist mein Code:Mockito: InvalidUseOfMatchersException

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

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

ich InetAddressFactory bin mit einer statischen Umsetzung der InetAddress Klasse zu verspotten. Hier ist der Code für die Fabrik:

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

Hier ist meine Einheit Testfall:

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

Ausnahme auf Lauf testPostDnsCheck() Test:

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

Jede Eingabe, wie dieses Problem zu lösen?

Antwort

156

Die Fehlermeldung skizziert die Lösung ziemlich deutlich. Die Linie

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

verwendet einen Rohwert und ein Matcher, wenn es erforderlich ist, entweder alle Rohwerte oder alle Matcher zu verwenden. Eine korrekte Version könnte lesen

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

Wie dumm von mir. Ich habe weiter analysiert, warum der zweite Parameter mir immer den Fehler gab. Danke fürs klarstellen. Ich bin sehr neu in Mockito, dies ist meine erste Begegnung. – devang

+1

Danke Mann. Die Ausnahmebedingungsnachricht, wenn sehr verwirrend, aber Ihre Erklärung war sehr klar zu verstehen –

17

ich jetzt das gleiche Problem für eine lange Zeit hatte, musste ich oft Matchers und Werte mischen und ich schaffte es nie bis vor kurzem mit Mockito .... zu tun! Ich lege die Lösung hier in der Hoffnung, es wird jemandem helfen, auch wenn dieser Beitrag ziemlich alt ist.

Es ist eindeutig nicht möglich, Matchers UND Werte zusammen in Mockito zu verwenden, aber was ist, wenn es einen Matcher gibt, der akzeptiert, eine Variable zu vergleichen? Das würde das Problem ... und in der Tat lösen ist: eq

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

In diesem Beispiel ‚metas‘ ist eine bestehende Liste von Werten

+4

Awesome. 'org.mockito.Mockito.eq()' – javaPlease42

+1

der richtige Import ist jetzt org.mockito.ArgumentMatchers.eq() – sam

6

Es könnte jemand in der Zukunft helfen: Mockito doesn‘ t unterstützen das Spotten von "finalen" Methoden (gerade jetzt). Es gab mir das gleiche InvalidUseOfMatchersException.

Die Lösung für mich bestand darin, den Teil der Methode, der nicht "endgültig" sein musste, in eine separate, zugängliche und übersteuerbare Methode zu stellen.

Überprüfen Sie die Mockito API für Ihren Anwendungsfall.