it-swarm.com.de

Wie kann ich eine Klasse testen, für die ein Webdienstaufruf erforderlich ist?

Ich versuche, eine Klasse zu testen, die einige Hadoop-Webdienste aufruft. Der Code hat so ziemlich die Form:

method() {
    ...use Jersey client to create WebResource...
    ...make request...
    ...do something with response...
}

z.B. Es gibt eine Methode zum Erstellen eines Verzeichnisses, eine Methode zum Erstellen eines Ordners usw.

Wie kann ich dies testen, da es sich bei dem Code um einen externen Webdienst handelt, über den ich keine Kontrolle habe? Ich könnte versuchen, den Webdienst-Client/die Antworten zu verspotten, aber das verstößt gegen die Richtlinie, die ich in letzter Zeit oft gesehen habe: "Verspotten Sie keine Objekte, die Sie nicht besitzen". Ich könnte eine Dummy-Webdienst-Implementierung einrichten - wäre das immer noch ein "Unit-Test" oder wäre es dann ein Integrationstest? Ist es einfach nicht möglich, einen Unit-Test auf diesem niedrigen Niveau durchzuführen - wie würde ein TDD-Praktiker vorgehen?

22
Chris Cooper

Meiner Meinung nach sollten Sie die Webservice-Aufrufe verspotten, wenn dies ein Komponententest ist, im Gegensatz zu einem Integrationstest.

Ihr Unit-Test sollte nicht testen, ob der externe Webservice funktioniert oder ob Ihre Integration korrekt ist. Beachten Sie, dass ein Nebeneffekt der Umwandlung Ihres Komponententests in einen Integrationstest darin besteht, dass er wahrscheinlich langsamer läuft, und Sie möchten schnell Komponententests.

Sollte dies dazu führen, dass Ihr Komponententest fehlschlägt, wenn der Webservice vorübergehend nicht verfügbar ist oder nicht ordnungsgemäß funktioniert? Es scheint nicht richtig. Ihr Komponententest sollte nur aus einem Grund fehlschlagen: Wenn der Code in dieser "Einheit" einen Fehler enthält.

Der einzige Teil des Codes, der hier relevant ist, ist ...do something with response.... Verspotten Sie den Rest.

42
Andres F.

Ich bin nicht einverstanden mit "verspotten Sie keine Objekte, die Sie nicht besitzen", wenn Sie Unit-Tests durchführen.

Verspotteter Existenzzweck ist die Tatsache, dass es Module, Bibliotheken und Klassen geben wird, die wir nicht besitzen werden.

Mein Vorschlag für Ihr Szenario ist, den Webdienstaufruf zu verspotten.

Richten Sie das Modell so ein, dass Daten an Ihr Modul zurückgegeben werden.
Stellen Sie sicher, dass Sie alle Szenarien abdecken, z. B. wenn die zurückgegebenen Daten null sind, wenn die zurückgegebenen Daten gültig sind usw.

Für den Code, den Sie besitzen, müssen Sie als Entwickler sicherstellen, dass der von Ihnen erstellte Code in allen Szenarien wie erwartet funktioniert.

6
Venu b

Ich würde so etwas wie EasyMock für diesen Test verwenden. Das Verspotten von Frameworks ist eine ideale Methode, um externe Abhängigkeiten von einer Klasse zu entfernen, und gibt Ihnen die vollständige Kontrolle über das Ergebnis externer Abhängigkeiten während der Tests. Um Ihr Beispiel ein wenig zu erweitern:

class WebClass {

private WebServiceInterface webserviceInterface;

    void method(){
        R result = webServiceInterface.performWebServiceCall();
        ... do something with result
    }

    public void setWebServiceInterface(WebServiceInterface webServiceInterface){
        this.webServiceInterface = webServiceInterface;
    }
}


interface WebServiceInterface {

   R performWebServiceCall();

}


class WebClassTest {

private WebServiceInterface mock;    
private R sampleResult = new R();

    @Before
    public void before(){
        mock = EasyMock.createMock(WebServiceInterface.class);
    }


    @Test
    public void test() {
        WebClass classUnderTest = new WebClass();
        EasyMock.expect(mock.performWebServiceCall()).andReturn(sampleResult);
        classUnderTest.setWebServiceInterface(mock);
        classUnderTest.method();
        EasyMock.verify(mock);
    }
}

Als erstes müssen Sie die Logik in Ihrer Klasse extrahieren, in der Sie Jersey verwenden, um eine WebResource abzurufen und den Webdienst in eine separate Klasse aufzurufen. Wenn Sie eine Schnittstelle für diese Klasse erstellen, können Sie ein Modell erstellen, dem Sie dann das Verhalten vorgeben können.

Sobald diese Schnittstelle erstellt wurde, können Sie mit EasyMock ein Modell erstellen, das ein bestimmtes Objekt für Ihren Testfall zurückgibt. Das obige Beispiel ist eine Vereinfachung der Strukturierung eines verspotteten Basistests und der Funktionsweise Ihrer Benutzeroberfläche.

Weitere Informationen zum Verspotten von Frameworks finden Sie unter diese Frage . In diesem Beispiel wird auch die Verwendung von Java) vorausgesetzt, aber Spott-Frameworks sind in allen Sprachen verfügbar, und obwohl sie unterschiedlich implementiert sind, funktionieren sie im Allgemeinen auf die gleiche Weise

1
Richard

Mocks sind in diesem Fall akzeptabel, aber Sie brauchen es nicht. Anstelle des Komponententests method() wird stattdessen nur der Teil getestet, der die Antwort verarbeitet.

Extrahieren Sie eine Funktion, die ResponseData (welcher Art auch immer geeignet ist) nimmt und dann die Aktion ausführt.

Anstatt zu verspotten, erstellen Sie jetzt einfach ein ResponseData-Objekt und übergeben es.

Sie können das Aufrufen des Dienstes vollständigen Integrationstests überlassen, die insgesamt method() abdecken

1
Daenyth

Was ich getan habe und es funktioniert:

  1. Lassen Sie alle Code-Webservices über einen Proxy aufrufen.
  2. Der Proxy ruft eine Klasse auf, die statisch weiß, ob wir einen Proxy verwenden oder nicht, und leitet entsprechend um. Mocks sind nur HashMaps, die für jede Anforderung eine bestimmte Antwort zurückgeben.
  3. Führen Sie die Tests mehrmals in dieser Reihenfolge aus:

3.1 Zunächst werden alle Webservices getestet. Von jeder Maschine sogar von Entwicklermaschinen. Dies sind die eigentlichen Webservices, die jedoch in der Entwicklungsumgebung ausgeführt werden. Dies bedeutet, dass Webservices niemals ausgefallen sein oder fehlerhafte Werte beantworten können, da sich sonst jeder Entwickler beschwert, dass er nicht kompilieren kann.

3.2 Anschließend werden alle anwendungsinternen Unit-Tests ausgeführt. Dies bedeutet, dass alle Webservices verspottet und getestet werden, indem dieselben Tests wie in 3.1 ausgeführt werden (und sie sollten ebenfalls bestanden werden, da sonst Mocks falsch sind) und von der realen Anwendung aufgerufen werden, als ob sie tatsächlich verwendet würden. Wenn die Mocks falsch sind, können Sie den Test in 3.1 ausführen und diese (Anforderungs-, Antwort-) Werte in einer HashMap aufzeichnen.

3.3 Dann werden die gleichen Tests wie in 3.2 ausgeführt, diesmal jedoch gegen die tatsächlichen Webservices, die in der Entwicklungsumgebung ausgeführt werden.

Nachdem all dies abgeschlossen ist, müssen Sie für die reale Produktionsumgebung nur die reale Adresse für jeden Webservice angeben. Hoffentlich erfordert dies nicht zu viele Änderungen in der Konfiguration.

0