EasyMock: Void-Methoden

Lesezeit: 5 Minuten

Benutzer-Avatar
Iker Jiménez

Ich habe eine Methode, die void in einer Klasse zurückgibt, die eine Abhängigkeit der Klasse ist, die ich testen möchte.

Diese Klasse ist riesig und ich verwende nur diese eine Methode daraus. Ich muss die Implementierung dieser Methode für den Test ersetzen, da ich möchte, dass sie etwas anderes macht, und ich muss auf die Parameter zugreifen können, die diese Methode empfängt.

Ich kann keine Möglichkeit finden, dies zu tun EasyMock. Ich glaube, ich weiß, wie man damit umgeht Mockito durch die Nutzung doAnswer aber ich möchte keine weitere Bibliothek hinzufügen, es sei denn, es ist absolut notwendig.

Benutzer-Avatar
matt b

Wenn ich verstehe, was Sie richtig machen wollen, sollten Sie in der Lage sein, zu verwenden andAnswer():

mockObject.someMethod(eq(param1), eq(param2));
expectLastCall().andAnswer(new IAnswer() {
    public Object answer() {
        //supply your mock implementation here...
        SomeClass arg1 = (SomeClass) getCurrentArguments()[0];
        AnotherClass arg2 = (AnotherClass) getCurrentArguments()[1];
        arg1.doSomething(blah);
        //return the value to be returned by the method (null for void)
        return null;
    }
});

Das EasyMock-Benutzerhandbuch erklärt:

Erstellen von Rückgabewerten oder Ausnahmen

Manchmal möchten wir, dass unser Scheinobjekt einen Wert zurückgibt oder eine Ausnahme auslöst, die zum Zeitpunkt des tatsächlichen Aufrufs erstellt wird. Seit EasyMock 2.2 wird das Objekt von zurückgegeben expectLastCall() und expect(T value) liefert die Methode andAnswer(IAnswer answer) welches erlaubt [you] um eine Implementierung der Schnittstelle anzugeben IAnswer die verwendet wird, um den Rückgabewert oder die Ausnahme zu erstellen.

Innen ein IAnswer callback, die an den Scheinaufruf übergebenen Argumente sind über verfügbar EasyMock.getCurrentArguments(). Wenn Sie diese verwenden, können Refactorings wie das Neuordnen von Parametern Ihre Tests beeinträchtigen. Du wurdest gewarnt.

Benutzer-Avatar
Edward Q. Brücken

Wenn Sie die void-Methode einfach jedes Mal aufrufen, wenn Sie erwarten, dass sie aufgerufen wird, und dann aufrufen EasyMock.expectLastCall() vor dem Anruf replay()Easymock „erinnert“ sich an jeden Aufruf.

Ich denke also nicht, dass Sie explizit anrufen müssen expect() (außer lastCall), da Sie nichts von einer void-Methode erwarten, außer ihrem Aufruf.

Danke Chris!

„Spaß mit EasyMock“ von Burt Beckwith, einem anderen StackOverflow-Benutzer, ist ein guter Blogbeitrag, der mehr Details enthält. Bemerkenswerter Auszug:

Grundsätzlich ist der Fluss, den ich neige dazu, zu verwenden:

  1. Erstellen Sie einen Schein
  2. Anruf expect(mock.[method call]).andReturn([result]) für jeden erwarteten Anruf
  3. Anruf mock.[method call]dann EasyMock.expectLastCall() für jeden erwarteten ungültigen Anruf
  4. Anruf replay(mock) um vom „Aufnahme“-Modus in den „Wiedergabe“-Modus zu wechseln
  5. injizieren Sie den Schein nach Bedarf
  6. Rufen Sie die Testmethode auf
  7. Anruf verify(mock) um sicherzustellen, dass alle erwarteten Anrufe erfolgt sind

  • Ich denke, diese Antwort geht nicht auf die Frage ein – er möchte nicht nur eine Erwartung an die Methode stellen, sondern auch deren Implementierung ersetzen.

    – matt b

    14. Mai 2009 um 13:43 Uhr

  • Guter Punkt Matt, andererseits hat mir dieser Beitrag geholfen zu erkennen, warum die Erwartungsmethode hier nicht wirklich anwendbar ist.

    – Peter Wippermann

    27. November 2012 um 7:49 Uhr

Wenn Sie nur für später auf die Parameter zugreifen möchten, werden Sie möglicherweise auch die zu schätzen wissen Erfasst Klasse, die neu in EasyMock 2.4 ist.

Anstelle eines Matchers können Sie eine Instanz der Klasse „Capture“ verwenden. Wenn Ihre simulierte Methode aufgerufen wird, speichert die Capture-Instanz den Parameter, mit dem sie aufgerufen wurde.

Capture<ChartPanel> captured = new Capture<ChartPanel>();
// setChartPanel is going to be called during execution;
// we want to verify some things about the ChartPanel
// instance it's invoked with
chartMock.setChartPanel(capture(captured));
replay(chartMock);

ufdm.setChartAnnotater(chartMock);
// afterPropertiesSet triggers the setChartPanel call...
ufdm.afterPropertiesSet();
verify(chartMock);

// verify some things about the ChartPanel parameter our
// mock object was invoked with
assertSame(plot, captured.getValue().getChart().getPlot());

Benutzer-Avatar
Josef Lust

Vielleicht möchten Sie PowerMock ausprobieren. EasyMock basiert auf der Proxy-Reflection-API, was bedeutet, dass alles ein Proxy ist und Sie nur Schnittstellen und damit nur nicht endgültige Methoden und Klassen testen können. Dies mag für einige funktionieren, aber wenn Sie die Welt wie gebaut testen, benötigen Sie mehr Leistung.

Mit PowerMock hebt die Java 5-Instrumentierungs-API die Einschränkungen auf. Es ist nicht erforderlich, Scheinobjektimplementierungen des zu testenden Objekts zu schreiben (nur hässlich, IMO). Koppeln Sie PowerMock mit Mockito (oder JMockit) und Sie werden wirklich zu den Rennen gehen.

Natürlich gibt es die andere Richtung, Ihren Code umzuschreiben, damit er leichter getestet werden kann, was im Allgemeinen auch eine gute Idee ist, wenn möglich.

In Situationen wie diesen habe ich festgestellt, dass das Erstellen einer verschachtelten Klasse in meiner Unit-Test-Klasse und das Überschreiben der Methoden mit speziellen Anforderungen auf diese Weise der beste Weg ist. Also, wenn Sie testen ClassA die diese Methode mit den Parametern hat, auf die Sie zugreifen müssen, würden Sie so etwas tun:

class MockClassA extends ClassA {
    @Override
    void specialMethod(String param1, String param2) {
        // do logging or manipulation of some sort
        super.specialMethod(param1,param2); // if you need to
    }
}

In meinem Unit-Testing-Code verwende ich dann stattdessen einfach diese Instanz. Behandeln Sie es einfach so, als wäre es ein beliebiges anderes Scheinobjekt. Viel einfacher als das Mischen von Bibliotheken, was meiner Meinung nach wahrscheinlich keine gute Idee ist.

  • Schon überlegt. Aber es ist eine abstrakte Klasse, also müsste ich etwa 20 leere Methodenimplementierungen bereitstellen oder eines ihrer Kinder ableiten, was für andere Entwickler, die sich den Test ansehen, etwas verwirrend sein könnte.

    – Iker Jiménez

    13. Mai 2009 um 16:48 Uhr

  • Oh, in Ordnung. Ich wusste nicht, dass es abstrakt ist. Wenn Sie eine IDE verwenden (ich nehme an, Sie verwenden Eclipse oder NetBeans), kann sie all diese abstrakten Methoden für Sie einbinden, und Sie können einfach einen Kommentar darüber kleben, der erklärt, was Sie tun. Keine sehr programmatische Lösung, aber zumindest werden andere Entwickler dadurch nicht verwirrt.

    – Markus W

    13. Mai 2009 um 16:52 Uhr

  • Schon überlegt. Aber es ist eine abstrakte Klasse, also müsste ich etwa 20 leere Methodenimplementierungen bereitstellen oder eines ihrer Kinder ableiten, was für andere Entwickler, die sich den Test ansehen, etwas verwirrend sein könnte.

    – Iker Jiménez

    13. Mai 2009 um 16:48 Uhr

  • Oh, in Ordnung. Ich wusste nicht, dass es abstrakt ist. Wenn Sie eine IDE verwenden (ich nehme an, Sie verwenden Eclipse oder NetBeans), kann sie all diese abstrakten Methoden für Sie einbinden, und Sie können einfach einen Kommentar darüber kleben, der erklärt, was Sie tun. Keine sehr programmatische Lösung, aber zumindest werden andere Entwickler dadurch nicht verwirrt.

    – Markus W

    13. Mai 2009 um 16:52 Uhr

1144180cookie-checkEasyMock: Void-Methoden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy