[JAVA] Implementieren Sie Test Double in JUnit, ohne externe Bibliotheken zu verwenden

Was ist ein Testdoppel?

Ein Wort, das vom englischen Wort "double" abgeleitet ist und einen Ersatz für einen Darsteller oder einen Schattenkrieger bedeutet. Im Allgemeinen Mock oder Stub genannt.

Warum Test Double verwenden?

Im Unit-Test des Systems ist das Testziel Es gibt wenige Fälle, in denen dies nicht von anderen Klassen oder externen Elementen abhängt. Abhängige Tests sind Tests nicht nur zum Thema, sondern auch zur Abhängigkeit.

Der Vorteil ist, dass der Test im selben Zustand wie beim Ausführen des Systems durchgeführt wird. Es gibt einen Aspekt, dass der Wert des Inhalts, der durch die Testergebnisse garantiert wird, zunimmt. Andererseits besteht der Nachteil darin, dass der Umfang der Ursachenanalyse größer wird, wenn der Test fehlschlägt. Wenn das Verarbeitungsergebnis des abhängigen Objekts nicht vorhergesagt werden kann, sinkt die Genauigkeit der Überprüfung.

Als Gegenmaßnahme gegen die oben genannten Nachteile anstelle der Faktoren, die den Test beeinflussen Es gibt eine Möglichkeit, die Unabhängigkeit des Tests zu erhöhen, indem Sie einen einfach zu testenden Ersatz verwenden. Es ist die Verwendung von Stubs und Mock (Test Double), um diese zu erreichen.

Unterschied zwischen Stub und Mock

Beide werden als Ersatz für die Klassen und Module verwendet, von denen das Testziel abhängt. Es gibt keinen Unterschied in Bezug auf Klassen und Module. Daher wird es oft als Synonym verwendet, aber im engeren Sinne gibt es die folgenden Unterschiede.

Stummel

** Der Zweck besteht darin, das abhängige Objekt auf vorhersehbare Weise zu verhalten **.

Darüber hinaus wird es als Ersatz für die folgenden Objekte verwendet.

spotten

** Der Zweck besteht darin, zu überprüfen, ob das abhängige Objekt während der Ausführung aufgerufen wurde **.

Verschiedene Testdoppel

Stub, der einen festen Wert zurückgibt

Verarbeitung, bei der es schwierig ist, den gewünschten Wert zu erhalten, wie Zufallszahlen und Systemdaten, Das Extrahieren als Methode und Klasse und das Wechseln mit einem Stub erleichtern das Testen. Es gibt verschiedene Möglichkeiten, Stubs zu implementieren. Die Details lauten jedoch "[Refactoring-Methode in JUnit](https://qiita.com/maple_syrup/items/c370f3f850972aafd101#junit%E3%81%AB%E3%81%8A%E3". % 81% 91% E3% 82% 8B% E3% 83% AA% E3% 83% 95% E3% 82% A1% E3% 82% AF% E3% 82% BF% E3% 83% AA% E3% 83 % B3% E3% 82% B0% E3% 81% AE% E6% 89% 8B% E6% B3% 95) ".

Im folgenden Beispiel wird der Prozess des Erfassens von Zufallszahlen als Methode herausgeschnitten. Sie haben eine Stub-Methode in Ihrem Testcode erstellt und überschrieben.

Produktionscode


public class GetRandomElementFromList {
	public <T> T choice(List<T> elements) {
		if (elements.size() == 0) {
			return null;
		}
		int idx = nextInt() % elements.size();
		return elements.get(idx);
	}

	int nextInt() {
		return new Random().nextInt();
	}
}

Testcode


public class GetRandomElementFromListTest {
	private List<String> elements = new ArrayList<>();
	
	@Before
	public void setUp() {
		elements.add("A");
		elements.add("B");
	}

	@Test
gibt A mit öffentlicher nichtiger Wahl zurück() {
		GetRandomElementFromList sut = new GetRandomElementFromList() {
			@Override
			int nextInt() {
				return 0;
			}
		};
		assertThat(sut.choice(elements), is("A"));
	}
	
	@Test
Gibt B mit öffentlicher nichtiger Wahl zurück() {
		GetRandomElementFromList sut = new GetRandomElementFromList() {
			@Override
			int nextInt() {
				return 1;
			}
		};
		assertThat(sut.choice(elements), is("B"));
	}
}

Stub löst eine Ausnahme aus

In vielen Fällen ist es schwierig, eine Ausnahme auszulösen, z. B. einen Datenbankverbindungsfehler. Auch in einem solchen Fall eine Methode, die eine Ausnahme auslöst Durch Schneiden in kleine Stücke ist es möglich, durch Stummel zu wechseln.

Spion: Ein Mock, der Objektaufrufe überwacht

Der grundlegende Komponententest überprüft den Eingabewert und den Ausgabewert wie die assertThat-Methode. Daher ist es einfach, ein Objekt zu testen, dessen Testziel einen Rückgabewert zurückgibt und seinen Status nicht beibehält. Andererseits ändert sich der Testfall, wenn sich der Status der Methode ohne Rückgabewert oder das Zielobjekt ändert Die Überprüfung wird schwierig. Die Überprüfung wird noch schwieriger, wenn sich der Status abhängiger Objekte ändert.

Ein typisches Beispiel für Nebenwirkungen bei abhängigen Objekten ist Der Inhalt wird in die Standardausgabe und den Logger geschrieben. (Da sich der Status abhängiger Objekte (Standardausgabe usw.) abhängig von der Ausführung des Testziels ändert.) Schreiben Sie in einem solchen Fall einen Logger oder ein Objekt, das die Standardausgabe ausführt. Es wird durch ein Objekt namens Spion ersetzt und überwacht die versteckte Verarbeitung. Der Spion verpackt und implementiert das ursprüngliche Objekt.

Im Folgenden finden Sie ein Implementierungsbeispiel für Testcode zum Überprüfen der Methode, mit der Protokolle ausgegeben werden.

Produktionscode


public class OutputLog {

    Logger logger = Logger.getLogger(OutputLog.class.getName());
    
    public void outputLog() {
        logger.info("doSomething");
    }
}

Testcode(Spionageklasse)


public class SpyLogger extends Logger{

    final Logger base;
    //Klassenvariable zum Referenzieren des Protokolls von der Testseite getrennt von der Protokollausgabe
    final StringBuffer log = new StringBuffer();
    
    public SpyLogger(Logger base) {
        super(base.getName(), base.getResourceBundleName());
        this.base = base;
    }
    
    //Methode, um ein Stummel zu sein
    @Override
    public void info(String message) {
        base.info(message);
        //Zusätzliche Verarbeitung → Ausgabe in den StringBuffer, über den der Spion unabhängig verfügt
        log.append(message);
    }
}

Testcode(Testfall)


public class SpyExampleTest {
    @Test
    public void test() {
        OutputLog sut = new OutputLog();
        SpyLogger spyLogger = new SpyLogger(sut.logger);
        //Ersetzen Sie den zu testenden Logger durch einen Spionage-Logger
        sut.logger = spyLogger;
        sut.outputLog();
        assertThat(spyLogger.log.toString(), is("doSomething"));
    }
}

Verweise

Dieser Artikel wurde unter Bezugnahme auf die folgenden Informationen verfasst.

Recommended Posts

Implementieren Sie Test Double in JUnit, ohne externe Bibliotheken zu verwenden
Implementieren Sie eine Freigabeschaltfläche in Rails 6, ohne Gem zu verwenden
Testen Sie die Klasse mit Feldinjektion im Spring-Boot-Test, ohne den Spring-Container zu verwenden
Testen Sie private Methoden in JUnit
Testen Sie private Methoden in JUnit
Implementieren Sie einen tabellengesteuerten Test in Java 14
JUnit-Testbericht in Maven ausgeben
[Spring MVC] Implementieren Sie die in der URL enthaltenen dynamischen Parameter ohne Verwendung von Optional (~ Java7).
Steuern Sie die Testreihenfolge in Junit4 mit einem Aufzählungstyp
Map ohne Verwendung eines Arrays in Java
Implementieren Sie Schaltflächenübergänge mit link_to in Rails
[Für Anfänger] Ich habe versucht, JUnit 5 mit Eclipse zu verwenden
JUnit 5: Wie man Testfälle in enum schreibt
Implementieren Sie die Teilübereinstimmungssuchfunktion ohne Ransuck
Implementieren Sie die Sternebewertungsfunktion mit Raty in Rails 6
Testcode mit Mock mit JUnit (EasyMock Center)