364 Stimmen

Kann Mockito eine Methode ohne Rücksicht auf das Argument stubben?

Ich versuche, einige Legacy-Code zu testen, mit Mockito.

Ich möchte einen Stummel FooDao die in der Produktion wie folgt verwendet wird:

foo = fooDao.getBar(new Bazoo());

Ich kann schreiben:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

Das offensichtliche Problem ist jedoch, dass getBar() wird nie mit demselben Bazoo Objekt, für das ich die Methode stubbed habe. (Verflucht sei das new Betreiber!)

Ich würde es lieben, wenn ich die Methode so einrichten könnte, dass sie folgende Ergebnisse liefert myFoo unabhängig von der Argumentation. Andernfalls höre ich mir andere Workaround-Vorschläge an, aber ich würde es wirklich gerne vermeiden, den Produktionscode zu ändern, bis es eine vernünftige Testabdeckung gibt.

542voto

Tomasz Nurkiewicz Punkte 322861
when(
  fooDao.getBar(
    any(Bazoo.class)
  )
).thenReturn(myFoo);

oder (zur Vermeidung von null s):

when(
  fooDao.getBar(
    (Bazoo)notNull()
  )
).thenReturn(myFoo);

Vergessen Sie nicht, Matcher zu importieren (viele andere sind verfügbar):

Für Mockito 2.1.0 und neuere Versionen:

import static org.mockito.ArgumentMatchers.*;

Für ältere Versionen:

import static org.mockito.Matchers.*;

24voto

Buhb Punkte 6838

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject() sollte Ihren Bedürfnissen entsprechen.

Außerdem können Sie jederzeit die Implementierung von hashCode() y equals() für die Bazoo Klasse. Dadurch würde Ihr Codebeispiel so funktionieren, wie Sie es wünschen.

18voto

So verwenden:

when(
  fooDao.getBar(
    Matchers.<Bazoo>any()
  )
).thenReturn(myFoo);

Bevor Sie importieren müssen Mockito.Matchers

7voto

Jose Martinez Punkte 10698

Eine andere Möglichkeit ist, sich auf die gute alte Mode zu verlassen equals Methode. Solange das Argument in der when Nachahmung equals das Argument in dem zu testenden Code, dann wird Mockito das Mock abgleichen.

Hier ist ein Beispiel.

public class MyPojo {

    public MyPojo( String someField ) {
        this.someField = someField;
    }

    private String someField;

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        MyPojo myPojo = ( MyPojo ) o;
        return someField.equals( myPojo.someField );
    }

}

dann, vorausgesetzt, Sie wissen, was der Wert für someField sein wird, können Sie sich so darüber lustig machen.

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

pros: Dies ist deutlicher als any übereinstimmen. Als Prüfer von Code halte ich ein Auge offen für any in den Code, den junge Entwickler schreiben, da es die Logik ihres Codes überprüft, um das entsprechende Objekt zu erzeugen, das übergeben wird.

Betrug: Manchmal ist das Feld, das an das Objekt übergeben wird, eine zufällige ID. In diesem Fall können Sie das erwartete Argument-Objekt nicht einfach in Ihrem Mock-Code konstruieren.

Ein anderer möglicher Ansatz ist die Verwendung von Mockitos Answer Objekt, das mit der Option when Methode. Answer können Sie den eigentlichen Aufruf abfangen, das Eingabeargument untersuchen und ein Scheinobjekt zurückgeben. In dem folgenden Beispiel verwende ich any um jede Anfrage an die Methode abzufangen, die nachgeahmt wird. Aber dann in der Answer lambda kann ich das Bazo-Argument weiter untersuchen... vielleicht um zu überprüfen, ob eine richtige ID übergeben wurde. Ich bevorzuge dies gegenüber any selbst, so dass zumindest eine Überprüfung des Arguments erfolgt.

    Bar mockBar = //generate mock Bar.

    when(fooDao.getBar(any(Bazo.class))
    .thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
        Bazo actualBazo = invocationOnMock.getArgument( 0 );

        //inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
        return mockBar;
    } );

Zusammenfassend kann man also sagen, dass ich mich gerne auf Folgendes verlasse equals (wobei das erwartete Argument und das tatsächliche Argument gleich sein sollten) und wenn "gleich" nicht möglich ist (weil ich den Zustand des tatsächlichen Arguments nicht vorhersagen kann), greife ich auf Answer um das Argument zu überprüfen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X