[Java] JUnit4-Testfallbeispiel

Mit @Rule nicht vertraut

Schreibst du JUnit? Du schreibst. Ich schreibe auch. Ich habe viele Projekte für Regierungsbüros, aber das Umfeld für Regierungsbüros, Finanzen und andere hart arbeitende Projekte ist normalerweise alt! Es gibt immer noch Java 6 und so weiter. …… Ab 2019 werden in der Regel sogar völlig neue Projekte mit Java 1.6 + Spring 1.x erstellt. Ich bin daher der Meinung, dass dies ein echtes Projekt für Regierungsbehörden und berühmte Unternehmen (außer IT-Unternehmen) ist: Freude: Als ich es zum ersten Mal berührte, war es noch JUnit3, aber jetzt ist JUnit4 der Mainstream. Ich habe JUnit 5 im Geschäftsleben (Projekte von Firmen) nicht gesehen, weil ich nicht die Mühe habe, den Testrahmen im bestehenden Projekt zu ändern.

Aber ich bin immer noch nicht an JUnit 4 gewöhnt ... Deshalb habe ich die Muster aufgeschrieben, die ich oft über die @ Rule-Annotation schreibe, die ich schreibe, indem ich jedes Mal google oder nach dem Code von Leuten suche. Als Gegenstand sieht es so aus.

Bei Verwendung von PowerMock

Ich habe es in [Supplement 2](# Supplement 2) ein wenig erwähnt, aber die Kompatibilität zwischen PowerMock und @Rule ist nicht sehr gut. PowerMockRule von PowerMock kann nicht verwendet werden, wobei erkannt wird, dass die Klasse eine @ RunWith-Annotation ist (@RunWith (PowerMockRunner.class)). Wenn Sie dann einen Nicht-Kompilierungsfehler oder einen Ausführungsfehler erhalten (PowerMock-bezogen oder das Objekt mit @Rule wird null oder funktioniert nicht gut), müssen Sie entweder @Rule oder PowerMock aufgeben.

Sample.java


public class Sample {
	public static boolean isEmpty(String value) {
		return (value == null || "".equals(value)) ? true : false;
	}

	public static int parseInt(String value) throws Exception {
		try {
			return Integer.parseInt(value);
		} catch (NumberFormatException e) {
			throw new Exception("", e);
		}
	}
}

Wenn Sie den Konstruktor mit PowerMock verspotten, besteht das Problem, dass mit EclEmma keine Abdeckung erzielt werden kann. (Dies kann in Abhängigkeit von der Kombination der Versionen gelöst werden.) Beispielcode Fehler beim Konvertieren des Testziels Wenn die Einstellung oder Zusicherung des Testcode-Modells kompliziert ist, wird die Methode für jeden Fall gekürzt, aber der Testfall einer statischen Allzweck-Dienstprogrammmethode ist wie folgt Ich werde mehrere Fälle mit einer Testmethode durchführen. Wenn das Argument eine Karte ist, wird die private Methode mit einem / getrennten String als Argument ausgeschnitten und vor dem Übergeben in eine Karte konvertiert. Eine Gruppe, die häufig private Methoden auch in Testklassen schneidet.

SampleTest.java


import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.text.DecimalFormat;
import java.text.MessageFormat;

import org.hamcrest.core.IsInstanceOf;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.hamcrest.Matcher;

public class SampleTest {
	//Anhäufung von Assert-Fehlern
	@Rule
	public ErrorCollector errs = new ErrorCollector();
	//Namen der Testmethode abrufen
	@Rule
	public TestName name = new TestName();
	//Ausnahme Assert Content-Einstellung
	@Rule
	public ExpectedException thrown = ExpectedException.none();
	//Ausgabe der Start- / Endnachricht
	@Rule
	public TestWatcher watcher = new TestWatcher() {
		@Override
		protected void starting(final Description desc) {
			System.out.println(MessageFormat.format("Test start. : {0}", desc));
		}

		@Override
		protected void succeeded(final Description desc) {
			System.out.println(MessageFormat.format("Test succeeded. : {0}", desc));
		}

		@Override
		protected void failed(final Throwable e, final Description desc) {
			System.err.println(MessageFormat.format("Test failed. : {0} \r\n*** Exception : {1}.", desc, e.getMessage()));
		}

		@Override
		protected void finished(final Description desc) {
			System.out.println(MessageFormat.format("Test Finished. : {0}", desc));
		}
	};

	@Test
	public void test_isEmpty() {
		String[][] args = new String[][]{
			new String[]{null, "true"},
			new String[]{"", "true"},
			new String[]{"ABC", "false"},
		};

		int i = 1;
		for (String[] arg : args) {
			//Fehler bestätigen
  			this.errs.checkThat(this.getAssertMsg(i++), 
  					Sample.isEmpty(arg[0]), is(Boolean.valueOf(arg[1])));
		}
	}

	@Test
	public void test_parseInt_Anormales System() throws Exception {
		//Auslösen einer ausgelösten Ausnahme
		this.thrown.expect(Exception.class);
		this.thrown.expectMessage("Konvertierungsfehler");
		this.thrown.expectCause(IsInstanceOf.<Throwable>instanceOf(NumberFormatException.class));

		Sample.parseInt("AAA");
	}

	private String getAssertMsg(int idx) {
		//Namen der Testmethode abrufen
		return this.name.getMethodName() + " : " + new DecimalFormat("000").format(idx);
	}
}

ErrorCollector Wenn in der altmodischen Zusicherung ○○ ein Assert-Fehler auftritt, endet die Testmethode dort. Wenn im Fall einer Testmethode, die die Testausführung und -zusicherung wie "test_isEmpty ()" in der obigen Quelle wiederholt, im ersten Fall ein Bestätigungsfehler auftritt, werden die Ergebnisse des zweiten und der nachfolgenden Fälle den ersten Bestätigungsfehler nicht verwalten. Ich kann es nicht bestätigen. Durch die Verwendung von ErrorCollector wird der auf dem Weg aufgetretene Assert-Fehler gespeichert und die nächste Verarbeitung ausgeführt. Sie können die vorrätigen Assert-Fehler im Feld für die Fehlersuche anzeigen, indem Sie die Testmethode in der Ansicht Eclipse JUnit auswählen.

TestName Empfohlen in Kombination mit Error Collector. Übergeben Sie beispielsweise eine Nachricht an das erste Argument von "checkThat", um leichter zu verstehen, wo der Assert-Fehler aufgetreten ist. In der obigen Quelle wird es in getAssertMsg (int idx) verwendet. In [Ergänzung 1](# Ergänzung 1) finden Sie ein Beispiel für das Abrufen eines Testmethodennamens, der TestName nicht verwendet.

ExpectedException Die Ausnahmebestätigung kann als "@Test (expected = Exception.class)" geschrieben werden, dies überprüft jedoch nur den ausgelösten Ausnahmetyp. Meldungen und Ursachenausnahmen können nicht überprüft werden ... Also habe ich es in try ~ catch geschrieben, aber wenn Sie @Rule verwenden können, können Sie es schneller schreiben. In der obigen Quelle wird nur der Typ für die Ursachenausnahme überprüft. Sie können die Nachricht jedoch gleichzeitig mit dem folgenden Gefühl überprüfen.

thrown.expectCause(allOf(
	instanceOf(NumberFormatException.class),
	hasProperty("message", is("Nachrichteninhalt"))));

ExpectedException.expectCause kann jedoch Probleme haben, da es nicht kompiliert werden kann, wenn es sich um eine alte Version handelt. In einem solchen Fall ist es besser, aufzugeben und mit try ~ catch zu schreiben. Jemand, der in einem vorhandenen Projekt stecken bleibt, ohne die Bibliothek zu aktualisieren ... Wenn es sich um JUnit 4.12 oder höher handelt, ist es meiner Meinung nach in Ordnung, das Beispiel zu schreiben. Mit 4.10 hat es nicht funktioniert ...

TestWatcher Diejenige, die mit Junit 4.11 oder höher verwendet werden kann. Sie können den aufzurufenden Prozess schreiben, bevor Sie den Test ausführen, wenn die Voraussetzungen nicht erfüllt sind, wenn der Test erfolgreich ist, wenn der Test fehlschlägt und nachdem der Test beendet ist. Wenn die Voraussetzung nicht erfüllt ist, wird sie nicht in die obige Quelle geschrieben, sondern übersprungen (AssumptionViolatedException, Description). Ich habe es nie benutzt. In der obigen Quelle wird das Protokoll an die Konsole ausgegeben, aber natürlich können Sie den Logger verwenden, um nicht nur die Konsole, sondern auch nach Belieben auszugeben. Es ist nicht entschieden, dass es überhaupt für die Protokollausgabe ist, daher frage ich mich, ob ich dies anstelle von @Before oder @After verwenden kann.

In Bezug auf die Ausführungsreihenfolge in Kombination mit @BeforeClass, @Before, @After, @AfterClass gab es einen Artikel, in dem das Überprüfungsergebnis veröffentlicht wurde. Weitere Informationen finden Sie weiter unten. JUnit4-Ausführungsreihenfolge --umezucolor-Tagebuch Bei dieser Ausführungsreihenfolge denke ich persönlich, dass es bei der von TestWatcher angegebenen Verarbeitung um die Protokollausgabe geht. Wenn Sie beispielsweise eine Datei jedes Mal löschen müssen, wenn Sie eine Testmethode ausführen, schreiben Sie sie mit @Before ...


Ausführungsbeispiel

In Eclipse werden die Fälle, in denen ein Assert-Fehler auftritt, zusammen in der Fehlerverfolgung der JUnit-Ansicht ausgegeben. Es ist ein angenommenes Ergebnis, das einen Assert-Fehler verursacht, und das von der Konsole ausgeführte Ergebnis sieht folgendermaßen aus. Übrigens, wenn Sie es von der Konsole aus ausführen, sieht es so aus. Ich habe das JUnit-Glas in lib gestellt. java -cp ./;./lib/*; org.junit.runner.JUnitCore SampleTest

JUnit version 4.12
.Test start. : test_parseInt_Anormales System(SampleTest)
Test succeeded. : test_parseInt_Anormales System(SampleTest)
Test Finished. : test_parseInt_Anormales System(SampleTest)
.Test start. : test_isEmpty(SampleTest)
Test failed. : test_isEmpty(SampleTest)
*** Exception : There were 2 errors:
  java.lang.AssertionError(test_isEmpty : 002
Expected: is <true>
     but: was <false>)
  java.lang.AssertionError(test_isEmpty : 003
Expected: is <false>
     but: was <true>).
Test Finished. : test_isEmpty(SampleTest)
EE
Time: 0.043
There were 2 failures:
1) test_isEmpty(SampleTest)
java.lang.AssertionError: test_isEmpty : 002
Expected: is <true>
     but: was <false>
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
        at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
        at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
        at SampleTest.test_isEmpty(SampleTest.java:64)
~ Ausgelassen ~
2) test_isEmpty(SampleTest)
java.lang.AssertionError: test_isEmpty : 003
Expected: is <false>
     but: was <true>
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
        at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
        at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
        at SampleTest.test_isEmpty(SampleTest.java:64)
~ Ausgelassen ~

FAILURES!!!
Tests run: 2,  Failures: 2

Ergänzung 1

Der Name der Testmethode kann auch aus dem Stack-Trace abgerufen werden. Es ist spät. Diese Methode ist seit langem bekannt. Da getStackTrace [2] die Tiefe des Stack-Trace ist, muss möglicherweise angepasst werden, wenn die Hierarchie zum Aufrufen der Testmethode in JUnit nicht konstant ist.

private String createAssertMsg(int idx) {
	return Thread.currentThread().getStackTrace[2].getMethodName() + " : " + new DecimalFormat("000").format(idx);
}

Ergänzung 2

Wenn Sie um @Rule herum versuchen, PowerMock zu verwenden und "@RunWith (PowerMockRunner.class)" zu schreiben, können Sie es außerdem nicht verwenden ... Manchmal. Es ist nicht völlig nutzlos, TestName und ErrorCollector können funktionieren oder nicht, aber warum ... Übrigens konnte ich die beiden oben genannten verwenden, als ich den DI of Spring kombinieren wollte und die Klassenanmerkung so war. Nun, die ExpectedException der Ausnahmevalidierung hat auch in diesem Fall nicht funktioniert, also habe ich sie mit try ~ catch geschrieben ...

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@PowerMockIgnore("javax.crypto.*")
public class SampleTest {

@PowerMockIgnore (" javax.crypto. * ") Ist kompatibel mit ClassCastException, die normalerweise nicht auftritt, wenn javax.crypto.Cipher mit einer Kombination aus Powermock und Spring verwendet wird. Es ist ein Ersatz für ein Memorandum, machen Sie sich also eine Notiz.

Wenn Sie PowerMock verwenden, können Sie möglicherweise nicht nur eine bestimmte Testmethode ausführen. Fügen Sie in diesem Fall "@ Ignore" anstelle von "@ Test" hinzu, mit Ausnahme der Testmethode, die Sie überprüfen möchten. PowerMock erhöht das, was Sie tun können, aber es erhöht auch das, was Sie nicht tun können. Manchmal denke ich, dass es ein wenig na ... …… Aber es ist großartig, statische Methoden verspotten zu können… wenn Sie einen Fehler mit der im Testziel aufgerufenen Standard-API verursachen möchten…

Ich möchte auch über Regelkette schreiben.

Recommended Posts

[Java] JUnit4-Testfallbeispiel
[Java] Testen Sie private Methoden mit JUnit
Primzahlbeurteilung Java
Einführung eines automatisierten Java-Tests mit JUnit 5 + Gradle
[Java] So testen Sie, ob es in JUnit null ist
[CircleCI 2.0] [Java] [Maven] [JUnit] Aggregieren Sie die JUnit-Testergebnisse mit CircleCI 2.0
Einführung automatisierter Java-Tests mit JUnit 5 + Apache Maven
Anwendungsbeispiel für Java Enum
JUnit Teststart versuchen Sie etwas
Einfaches Memo von JUnit of Java
Java Unit Test Library-Arterien-Probe
Java Servlet LifeCycle-Beispiel
Testfall erstellen
Machen Sie einen Unit-Test mit Junit.
Rufen Sie den Namen des Testfalls in der JUnit-Testklasse ab
Testen Sie die Web-API mit junit
Testen Sie private Methoden in JUnit
Schnellstes Primzahl-Beurteilungsprogramm C # Java C ++
Sammlung von Java-Testcode-Methoden
2018 Java Proficiency Test für Newcomer-Basics-
Testen Sie private Methoden in JUnit
[JUnit] Testen Sie die ausgelöste Ausnahme
Ich habe Randoop untersucht, einen JUnit-Testklassengenerator für Java.
[Java] Ich möchte Standardeingabe und Standardausgabe mit JUnit testen
Implementieren Sie einen tabellengesteuerten Test in Java 14
Java Unit Test Library-Arterie-ArValidator Validiert Objekte
Beispiel für Codierung und Decodierung in Java
Java Unit Test Library-Arterie-Aktuelles Datum Beurteilung
Testinhalt der Java SE Bronze Prüfung
Einführung in Java-Tipps GreenMail zu Junit5
JUnit-Testbericht in Maven ausgeben
Java Unit Test Library-Arterie / JUnit4-Array-Äquivalenz
Testen Sie den Spring Framework Controller mit Junit