Ich muss Teufel spielen, die sich ein bisschen für diese Frage einsetzen, weil ich sie wegen mangelnder Erfahrung nicht gut verteidigen kann. Hier ist der Deal, ich verstehe konzeptionell die Unterschiede zwischen Unit-Test und Integrationstest. Wenn sich ein Unit-Test speziell auf Persistenzmethoden und das Repository konzentriert, wird möglicherweise über ein Framework wie Moq ein Mock verwendet, um zu bestätigen, dass eine gesuchte Bestellung wie erwartet zurückgegeben wurde.
Angenommen, ich habe den folgenden Komponententest erstellt:
[TestMethod]
public void GetOrderByIDTest()
{
//Uses Moq for dependency for getting order to make sure
//ID I set up in 'Arrange' is same one returned to test in 'Assertion'
}
Wenn ich es also einrichte OrderIdExpected = 5
und mein Scheinobjekt 5
als ID zurückgibt, besteht mein Test. Ich verstehe es. Ich habe den Code getestet , um sicherzustellen, dass meine Code-Preforms das erwartete Objekt und die erwartete ID und nicht etwas anderes zurückgeben.
Das Argument, das ich bekommen werde, ist folgendes:
"Warum nicht einfach die Komponententests überspringen und Integrationstests durchführen? Es ist wichtig, die gespeicherte Datenbankprozedur und Ihren Code zusammen zu testen . Es scheint zu viel zusätzliche Arbeit zu sein, Komponententests und Integrationstests durchzuführen, wenn ich letztendlich wissen möchte, ob die Datenbank aufruft und der Code funktionieren. Ich weiß, dass die Tests länger dauern, aber sie müssen ausgeführt und getestet werden, so dass es für mich sinnlos erscheint, beides zu haben. Testen Sie nur, worauf es ankommt. "
Ich könnte es mit einer Lehrbuchdefinition verteidigen wie: "Nun, das ist ein Integrationstest und wir müssen den Code separat als Unit-Test testen und, yada, yada, yada ..." Dies ist ein Fall, in dem eine puristische Erklärung der Praktiken erfolgt Die Realität verliert sich. Ich stoße manchmal darauf und wenn ich die Argumentation hinter Unit-Testing-Code, der letztendlich von externen Abhängigkeiten abhängt, nicht verteidigen kann, kann ich keine Argumentation dafür abgeben.
Jede Hilfe zu dieser Frage wird sehr geschätzt, danke!
quelle
Antworten:
Unit-Tests und Integrationstests dienen unterschiedlichen Zwecken.
Unit-Tests verifizieren die Funktionalität Ihres Codes ... dass Sie das, was Sie von der Methode erwarten, zurückerhalten, wenn Sie sie aufrufen. Integrationstests testen, wie sich der Code verhält, wenn er als System kombiniert wird. Sie würden nicht erwarten, dass Unit-Tests das Systemverhalten bewerten, und Sie würden auch nicht erwarten, dass Integrationstests bestimmte Ausgaben einer bestimmten Methode verifizieren.
Unit-Tests sind bei korrekter Durchführung einfacher einzurichten als Integrationstests. Wenn Sie sich ausschließlich auf Integrationstests verlassen, werden Ihre Tests wie folgt ausgeführt:
Fazit: Verwenden Sie Integrationstests , um zu überprüfen , dass die Verbindungen zwischen den Objekten richtig funktionieren, aber Anlehnen Einheit testen ersten funktionale Anforderungen zu überprüfen.
Trotzdem müssen Sie für bestimmte Repository-Methoden möglicherweise keine Komponententests durchführen. Unit - Tests sollten nicht auf getan werden trivial Methoden; Wenn Sie lediglich eine Anforderung für ein Objekt an den von ORM generierten Code übergeben und ein Ergebnis zurückgeben, müssen Sie dies in den meisten Fällen nicht in einem Komponententest durchführen. ein integrationstest ist ausreichend.
quelle
Ich bin auf der Seite der Pragmatiker. Testen Sie Ihren Code nicht zweimal.
Wir schreiben nur Integrationstests für unsere Repositories. Diese Tests sind nur von einer einfachen Testkonfiguration abhängig, die für eine speicherinterne Datenbank ausgeführt wird. Ich denke, sie bieten alles, was ein Komponententest leistet, und noch viel mehr.
quelle
Unit-Tests bieten einen Grad an Modularität, den Integrationstests (von Entwurf her) nicht bieten können. Wenn ein System überarbeitet oder neu zusammengestellt wird (und dies wird passieren), können Komponententests häufig wiederverwendet werden, während Integrationstests häufig neu geschrieben werden müssen. Integrationstests, die versuchen, die Arbeit von etwas zu erledigen, das in einem Komponententest enthalten sein sollte, sind oft zu viel, was es schwierig macht, sie zu warten.
Darüber hinaus bietet das Testen von Einheiten die folgenden Vorteile:
Sie können Ihre Arbeit aufteilen (und einen DRY-Ansatz durchsetzen), indem Sie sowohl Unit- als auch Integrationstests verwenden. Verlassen Sie sich bei kleinen Funktionseinheiten einfach auf Komponententests, und wiederholen Sie keine Logik, die bereits in einem Komponententest enthalten ist, in einem Integrationstest. Dies führt häufig zu weniger Arbeit (und damit zu weniger Nacharbeit).
quelle
Tests sind nützlich, wenn sie unterbrochen werden: Proaktiv oder reaktiv.
Unittests sind proaktiv und können eine kontinuierliche Funktionsüberprüfung sein, während Integrationstests auf inszenierte / gefälschte Daten reagieren.
Wenn das betrachtete System mehr von Daten als von der Berechnungslogik abhängig ist, sollten Integrationstests an Bedeutung gewinnen.
Wenn wir zum Beispiel ein ETL-System erstellen, werden die relevantesten Tests Daten betreffen (inszeniert, gefälscht oder live). Das gleiche System wird einige Unit-Tests haben, aber nur in Bezug auf Validierung, Filterung usw.
Das Repository-Muster sollte keine Computer- oder Geschäftslogik enthalten. Es ist sehr nah an der Datenbank. Das Repository steht jedoch auch in enger Beziehung zur Geschäftslogik, die es verwendet. Es geht also darum, ein GLEICHGEWICHT zu erzielen.
Unit Tests können testen, wie sich das Repository verhält. Integrationstests können testen, WAS WIRKLICH PASSIERT, als das Repository aufgerufen wurde.
Nun, "WAS WIRKLICH PASSIERT" scheint sehr verlockend zu sein. Dies kann jedoch sehr teuer sein, wenn Sie ständig und wiederholt ausgeführt werden. Hier gilt die klassische Definition von Sprödigkeitstests.
Die meiste Zeit finde ich es einfach gut genug, Unit-Test für ein Objekt zu schreiben, das das Repository verwendet. Auf diese Weise testen wir, ob die richtige Repository-Methode aufgerufen wurde und ob die richtigen verspotteten Ergebnisse zurückgegeben werden.
quelle
Es gibt drei verschiedene Dinge, die getestet werden müssen: die gespeicherte Prozedur, den Code, der die gespeicherte Prozedur aufruft (dh Ihre Repository-Klasse), und den Consumer. Die Aufgabe des Repositorys besteht darin, eine Abfrage zu generieren und den zurückgegebenen Datensatz in ein Domänenobjekt zu konvertieren. Es gibt genug Code, um Unit-Tests zu unterstützen, die von der tatsächlichen Ausführung der Abfrage und der Erstellung des Datensatzes getrennt sind.
Also (dies ist ein sehr sehr vereinfachtes Beispiel):
Übergeben Sie dann beim Testen
OrderRepository
ein verspottetesISqlExecutor
Objekt, und überprüfen Sie, ob das zu testende Objekt in der richtigen SQL (das ist sein Job) übergeben wurde, und geben Sie ein korrektesOrder
Objekt mit einem bestimmten Ergebnisdatensatz zurück (ebenfalls verspottet). Wahrscheinlich ist der einzige Weg, die konkreteSqlExecutor
Klasse zu testen, mit Integrationstests, fair genug, aber das ist eine Thin-Wrapper-Klasse und wird sich selten ändern, so große Sache.Sie müssen Ihre gespeicherten Prozeduren auch noch Unit-testen.
quelle
Ich kann dies auf einen sehr einfachen Gedankengang reduzieren: Bevorzugen Sie Unit-Tests, weil sie das Auffinden von Fehlern erleichtern. Und tun Sie dies konsequent, weil Inkonsistenzen Verwirrung stiften.
Weitere Gründe leiten sich aus denselben Regeln ab, die die OO-Entwicklung leiten, da sie auch für Tests gelten. Zum Beispiel das Prinzip der einmaligen Verantwortung.
Wenn einige Komponententests als nicht wert erscheinen, ist dies möglicherweise ein Zeichen dafür, dass das Thema nicht wirklich wert ist. Oder vielleicht ist seine Funktionalität abstrakter als sein Gegenstück, und die Tests dafür (sowie sein Code) können auf eine höhere Ebene abstrahiert werden.
Wie bei allem gibt es Ausnahmen. Und das Programmieren ist immer noch eine Kunstform, so dass viele Probleme unterschiedlich genug sind, um jeden für den besten Ansatz zu bewerten.
quelle