Wie mock-statische member-Variablen
Habe ich eine Klasse ClassToTest, die eine Abhängigkeit von ClassToMock.
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
protected void someMethod() {
...
}
}
Den unit-test-Fall für ClassToTest.
public class ClassToTestTest {
private ClassToMock _mock;
@Before
public void setUp() throws Exception {
_mock = mock(ClassToMock.class)
}
}
Beim verspotten heißt in der Methode setUp (), FileReader.readMemeber1(); ausgeführt wird. Gibt es eine Möglichkeit dies zu vermeiden? Ich denke, eine Möglichkeit ist die Initialisierung der MEMBER_1 innerhalb einer Methode. Irgendwelche anderen alternativen?
Dank!
- Ich denke, dass es tools gibt, die es ermöglichen, Sie zu verspotten, sich statische Variablen, aber Sie beinhalten eine Menge hacks. Da diese Klasse ist schwierig zu testen, zu hören, was die tests werden versuchen, Ihnen zu sagen, und machen Sie Ihre Klasse mehr lose gekoppelt
FileReader
. - Frage: Ist Ihre Sorge nur, dass
FileReader.readMember
ausgeführt wird (D. H., dass unit-tests sollten nicht auf die Datei system), oder sind Sie auch wollen, verschiedene tests, verschiedene Werte für MEMBER_1? - Ja. Ich will nicht mit FileReader.readMember ausgeführt werden. Es ist eine andere Abhängigkeit.
- Ich füge einen weiteren Schritt in meiner Antwort, dies sollte Ihr problem lösen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre
ClassToMock
eng gekoppelt mitFileReader
, das ist, warum Sie nicht in der Lage sind test/mock es. Anstelle der Verwendung von Werkzeug, hack-byte-code, so können Sie verspotten es. Ich würde vorschlagen, Sie einige einfache refactorings an der abhngigkeit.Schritt 1. Kapseln Von Globalen Referenzen
Diese Technik wird auch eingeführt in Michael Feathers ' s wunderbares Buch : Working effectively with Legacy Code.
Den Titel ziemlich viel selbst erklärt. Statt direkt auf eine Globale variable, gekapselt in einer Methode.
In deinem Fall
ClassToMock
umgestaltet werden kann in dieser :dann kannst du einfach mit Hilfe von Mockito zu verspottengetMemberOne()
.AKTUALISIERT Alten Schritt 1 kann nicht garantieren
Mockito
mock sicher, wennFileReader.readMemeber1()
Ausnahme auslösen, dann wird der test failled kläglich. So schlage ich vor, einen weiteren Schritt hinzuzufügen, um um ihn zu arbeiten.Schritt 1.5. hinzufügen der Setter-und Lazy-Getter
Da das problem ist
FileReader.readMember1()
wird aufgerufen, sobaldClassToMock
geladen wird. Wir haben, um es zu verzögern. So machen wir die getter-AufrufFileReader.readMember1()
träge, und öffnen Sie ein setter.Nun sollten Sie in der Lage, eine gefälschte
ClassToMock
auch ohneMockito
. Dies sollte jedoch nicht der Letzte Stand des Codes, sobald Sie Ihren test bereit, sollten Sie mit Schritt 2 fortfahren.Schritt 2. Abhängigkeit Injektion
Sobald Sie Ihren test bereit, Sie sollten es umgestalten weitere mehr. Jetzt zu Lesen, Anstatt die
MEMBER_1
von selbst. Diese Klasse sollte erhalten dieMEMBER_1
von der Außenwelt statt. Sie können entweder einen setter oder Konstruktor, um es zu empfangen. Unten ist der code, die Verwendung von setter.Dieser zwei-Schritt-refactorings sind wirklich einfach zu tun, und Sie können es tun, auch ohne test in die hand. Wenn der code ist nicht so Komplex sind, können Sie nur Schritt 2. Dann können Sie ganz einfach testen
ClassToTest
UPDATE 12/8 : Antwort der Kommentar
Siehe meine andere Antwort in dieser Frage.
Mocktio
mock richtig. Ich füge einen weiteren Schritt zur Umgehung des Problems.UPDATE 12/8 : Antwort der Kommentar
Es hängt davon ab.
Gibt es etwas, was Sie wollen, zu denken, bevor Sie tun eine massive Umgestaltung so.
Wenn ich mich bewege
FileReader
außerhalb, habe ich eine geeignete Klasse zum Lesen aus der Datei und geben Sie das Ergebnis jede einzelne Klasse, die Sie braucht ?Neben making-Klassen einfacher zu testen, erhalte ich andere Vorteile ?
Habe ich Zeit ?
Wenn eine der Antworten "NEIN" ist, dann sollten Sie besser nicht.
Jedoch, wir können immer noch brechen die Abhängigkeit zwischen den Klassen und
FileReader
mit minimalen änderungen.Ihre Frage und einen Kommentar, ich nehme an, Ihr system mit
FileReader
als Globale Referenz für lesestoff aus einer properties-Datei, dann geben Sie Sie an den rest des Systems.Diese Technik wird auch eingeführt in Michael Feathers ' s wunderbares Buch : Working effectively with Legacy Code, wieder.
Schritt 1. Delegieren
FileReader
statische Methoden zum Beispiel.Ändern
Zu
Dadurch werden statische Methoden in
FileReader
jetzt keine Kenntnis darüber, wiegetMemberOne()
Schritt 2. Interface extrahieren von
FileReader
Wir alle extrahieren der Methode
AppProperties
und statische Instanz inFileReader
jetzt mitAppProperties
.Schritt 3. Statische setter -
Eröffneten wir eine Naht in der FileReader. Indem wir dies tun, können wir ändern die zugrunde liegenden Instanz in
FileReader
und es würde nie auffallen.Schritt 4. Clean up
Nun
FileReader
haben zwei Aufgaben. Ist man Dateien Lesen und geben das Ergebnis ein anderes ist ein globaler Verweis für system.Können wir trennen Sie und geben Ihnen eine gute Namensgebung. Hier ist das Ergebnis :
ENDE.
Nach diesem refactoring, Wann immer Sie wollen zu testen. Sie können einen mock
AppProperties
zuGlobalAppProperties
Denke ich, dass diese Umgestaltung besser wäre, wenn alles, was Sie tun möchten, brechen Sie die gleichen globalen Abhängigkeit in vielen Klassen.