it-swarm.com.de

Letzte Methode Spott

Ich brauche etwas Übung mit der Endmethode mit Mockito. Ich habe so etwas geschrieben 

@Test
public void test() {
    B b = mock(B.class);
    doReturn("bar called").when(b).bar();   
    assertEquals("must be \"overrided\"", "bar called", b.bar());
    //bla-bla
}


class B {
    public final String bar() {
        return "fail";
    }
}

Aber es scheitert. Ich habe etwas "Hack" ausprobiert und es funktioniert.

   @Test
   public void hackTest() {
        class NewB extends B {
            public String barForTest() {
                return bar();
            }
        }
        NewB b = mock(NewB.class);
        doReturn("bar called").when(b).barForTest();
        assertEquals("must be \"overrided\"", "bar called", b.barForTest());
    }

Es funktioniert, aber "riecht".

Wo ist der richtige Weg?

Vielen Dank.

51
Stan Kurilin

Es gibt keine Unterstützung für die Verspottung der finalen Methoden in Mockito.

Wie Jon Skeet kommentierte, sollten Sie nach Möglichkeiten suchen, um die Abhängigkeit von der endgültigen Methode zu vermeiden. Allerdings gibt es einige Wege durch Bytecode-Manipulation (z. B. mit PowerMock).

Ein Vergleich zwischen Mockito und PowerMock wird die Dinge im Detail erklären.

28
iwein

Aus dem Mockito FAQ :

Was sind die Einschränkungen von Mockito

  • Die finalen Methoden können nicht simuliert werden - ihr tatsächliches Verhalten wird ohne Ausnahme ausgeführt. Mockito kann Sie nicht vor verspotteten Endmethoden warnen.
30
matt b

Sie können Powermock zusammen mit Mockito verwenden, dann müssen Sie B.class nicht unterteilen. Fügen Sie dies ganz oben in Ihre Testklasse ein

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)

@PrepareForTest weist Powermock an, B.class zu instrumentieren, um die endgültigen und statischen Methoden spöttisch zu machen. Ein Nachteil dieses Ansatzes ist, dass Sie den PowerMockRunner verwenden müssen, der die Verwendung anderer Testläufer wie dem Spring-Testläufer ausschließt.

17
Justin Rowe

Mockito 2 unterstützt jetzt verspottete finale Methoden, aber das ist eine "Inkubationsfunktion". Zur Aktivierung sind einige Schritte erforderlich, die hier beschrieben werden: https://github.com/mockito/mockito/wiki/What's-new-in-Mockito-2#mock-the-unmockable-opt- In-mocking-of-final-Klassenmethoden

13
WindRider

Angenommen, die Klasse B ist wie folgt:

class B {
    private String barValue;
    public final String bar() {
        return barValue;
    }
    public void final setBar(String barValue) {
        this.barValue = barValue;
    }
}

Es gibt einen besseren Weg, dies ohne das PowerMockito-Framework zu tun. Sie können einen SPY für Ihre Klasse erstellen und Ihre endgültige Methode überlisten. Sie können dies folgendermaßen tun:

@Test
public void test() {

    B b  = new B();
    b.setBar("bar called") //This should the expected output:final_method_bar()
    B spyB = Mockito.spy(b);
    assertEquals("bar called", spyB.bar());

}
3

Mockito 2.x unterstützt jetzt die letzte Methode und die letzte Klasse.

Aus den Dokumenten :

Das Verspotten der letzten Klassen und Methoden ist eine großartige Option. Diese Funktion muss explizit aktiviert werden, indem die Datei src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker mit einer einzelnen Zeile erstellt wird:

mock-maker-inline

Nachdem Sie diese Datei erstellt haben, können Sie Folgendes tun:

final class FinalClass {
  final String finalMethod() { return "something"; }
}

FinalClass concrete = new FinalClass(); 

FinalClass mock = mock(FinalClass.class);
given(mock.finalMethod()).willReturn("not anymore");

assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

In nachfolgenden Meilensteinen wird das Team eine programmatische Verwendung dieser Funktion ermöglichen. Wir werden alle nicht zu übersetzenden Szenarien identifizieren und unterstützen.

2

Ich habe gerade dasselbe getan. In meinem Fall wollte ich sicherstellen, dass die Methode keinen Fehler "verursacht" hat. Da es sich jedoch um eine catch/log/return-Methode handelt, konnte ich sie nicht direkt testen, ohne die Klasse zu ändern.

Ich wollte den Logger, den ich übergeben habe, einfach nur verspotten, aber etwas über das Spotteln der "Log" -Oberfläche schien nicht zu funktionieren, und das Spotteln einer Klasse wie "SimpleLog" funktionierte nicht, da diese Methoden endgültig sind.

Am Ende habe ich eine anonyme innere Klasse erstellt, die SimpleLog erweitert und die "log (level, string, error)" -Methode der Basisebene überschreibt, an die alle anderen delegieren, und dann auf einen Aufruf mit einer "level" von 5 wartet.

Im Allgemeinen ist das Erweitern einer Klasse für Verhalten nicht wirklich eine schlechte Idee. Wenn Sie nicht zu kompliziert ist, sollten Sie sich trotzdem lustig machen.

0
Bill K