[Java] Testen Sie private Methoden mit JUnit

Rufen Sie eine private Methode als Test auf

Zuvor konnten in Was Sie beim Schreiben von Java beachten sollten ** private Methoden durch Reflektion aufgerufen werden, sodass Zugriffsmodifikatoren nur zum Testen verwendet werden. Ich habe geschrieben, dass Sie es nicht löschen sollten **. Hier ist ein Beispiel.

Wenn es sich um ein Feld anstelle einer Methode handelt, schreiben Sie es wie folgt. → Private Variablen in Reflexion verweisen / setzen

2018/12/26 Hinzugefügt "Private Konstruktor aufrufen"

Vor- und Nachteile des Testens nach privater Methode

Wir sind uns bewusst, dass es eine Meinung gibt, dass "es von der öffentlichen Methode aufgerufen werden sollte, um die private Methode konsistent zu testen". Abhängig vom Projekt gibt es jedoch viele Fälle, die eine methodenbasierte test = private Methode enthalten. Es ist eine Regel. Jeder schreibt den Testcode entsprechend. Selbst wenn Sie es brechen, werden Sie nur aufgefordert, es neu zu schreiben. In der Geschäftslogik kann es eine öffentliche Methode in einer Klasse geben. In einem solchen Fall ist der Test ebenfalls schwierig. Es ist einfacher, einen Test für eine öffentliche Methode zu schreiben, nachdem die Verarbeitung für jede private Methode mit einem Test garantiert wurde. Aus diesem Grund liegen die Vor- und Nachteile des Testens nach einer privaten Methode außerhalb des Anwendungsbereichs.


Der Beispielcode lässt Javadoc weg und irgendwie. Ich habe den Vorgang bestätigt, damit er mit Kopieren und Einfügen funktioniert, aber es ist nur ein Beispielcode und eine Referenz.

Zu testende Klasse

Sample.java


public class Sample {
	private String strValue = null;

	public Sample(String value) {
		this.strValue = (value == null) ? "" : value;
	}

	/** 5.Rufen Sie den privaten Konstruktor auf*/
	private Sample() {
	}

	/** 1.Aufrufen einer nicht statischen Methode*/
	private boolean equals(String value) {
		return this.strValue.equals(value);
	}

	/** 2.Eine statische Methode aufrufen*/
	private static boolean isEmpty(String value) {
		return (value == null || "".equals(value)) ? true : false;
	}

	/** 3.Aufruf ohne Rückgabewert oder Argument*/
	private static void dispMessage() {
		System.out.println("Hello world!");
	}

	/** 4.Auf Ausnahmen prüfen*/
	private void setValue(String value) {
		if (value == null || value.isEmpty()) {
			throw new IllegalArgumentException("argument is empty.");
		}
		this.strValue = value;
	}
}

1. Aufrufen einer nicht statischen Methode

doPrivateMethod ist die Methode zum Aufrufen der zu testenden privaten Methode. In Typen werden die Typen der Argumente der privaten Methode in der Reihenfolge ab dem ersten Argument in einem Array gespeichert und übergeben. args übergibt die Argumente auch selbst. Da der Name der zu testenden Methode, der Typ und die Anzahl der Argumente angegeben sind, schlägt der Test fehl, wenn der Bereich durch Refactoring oder dergleichen geändert wird. (InvocationTargetException tritt auf)

SampleTest.java


import static org.junit.Assert.*;

import java.lang.reflect.Method;
import org.junit.Test;

public class SampleTest {
	@Test
	public void test_equals() throws Exception {
		Sample testee = new Sample("test");
		assertTrue((boolean) this.doPrivateMethod(
				testee, "equals", new Class[]{String.class}, new Object[]{"test"}));
	}

	/**
	 *Nicht statischer Methodenaufruf.
	 * 
	 * @param obj Getestetes Objekt
	 * @Parametername Name der getesteten Methode
	 * @Parametertypen Argumenttypen der zu testenden Methode
	 * @param args Argumente der zu testenden Methode
	 * @return Rückgabewert der nicht statischen Methode
	 */
	private Object doPrivateMethod(
		Object obj, String name, Class[] types, Object[] args) throws Exception {
		//Informieren Sie sich über die zu testende Methode
		Method method = obj.getClass().getDeclaredMethod(name, types);
		//Entfernen Sie die Zugriffsbeschränkungen für die zu testende Methode
		method.setAccessible(true);
		//Getesteter Methodenaufruf
		return method.invoke(obj, args);
	}
}

2. Rufen Sie die statische Methode auf

doStaticPrivateMethod ist die Methode zum Aufrufen der zu testenden privaten Methode. Diejenigen, die für Refactoring anfällig sind, sind die gleichen wie 1. Da es sich um einen Aufruf einer statischen Methode handelt, wird kein Objekt als Argument übergeben.

SampleTest.java


import static org.junit.Assert.*;

import java.lang.reflect.Method;
import org.junit.Test;

public class SampleTest {
	@Test
	public void test_isEmpty() throws Exception {
		assertTrue((boolean) this.doStaticPrivateMethod(
				"isEmpty", new Class[]{String.class}, new Object[]{null}));
	}

	/**
	 *statischer Methodenaufruf.
	 * 
	 * @Parametername Name der getesteten Methode
	 * @Parametertypen Argumenttypen der zu testenden Methode
	 * @param args Argumente der zu testenden Methode
	 * @Rückgabewert der statischen Methode
	 */
	private Object doStaticPrivateMethod(
		String name, Class[] types, Object[] args) throws Exception {
		//Informieren Sie sich über die zu testende Methode
		Method method = Sample.class.getDeclaredMethod(name, types);
		//Entfernen Sie die Zugriffsbeschränkungen für die zu testende Methode
		method.setAccessible(true);
		//Getesteter Methodenaufruf
		return method.invoke(null, args);
	}
}

assertTrue((boolean) this.doStaticPrivateMethod("isEmpty", new Class[]{String.class}, new Object[]{null}));

Wenn Sie in einer Methode mit Argumenten null übergeben möchten, fügen Sie sie in ein Array ein. Ein Array ist auch mit einem Argument erforderlich. Wenn Sie es so übergeben, wie es ist, wird es fehlschlagen.

3. Wert / Aufruf ohne Argument zurückgeben

Wenn die zu testende Methode ungültig ist, gibt es keinen Rückgabewert. (Null, auch wenn Sie versuchen, es aufzuheben) Übergeben Sie null, wenn Sie eine Methode ohne Argumente aufrufen. Im Gegensatz zu 2. muss es kein Array sein.

SampleTest.java


import static org.junit.Assert.*;

import java.lang.reflect.Method;
import org.junit.Test;

public class SampleTest {
	@Test
	public void test_dispMessage() throws Exception {
		this.doStaticPrivateMethod("dispMessage", null, null);
	}
}

** Aus Kommentaren hinzugefügt **

this.doStaticPrivateMethod("dispMessage", null, null);

Es wird nicht behauptet, da es sich um eine Beispielaufrufmethode handelt. Selbst beim Testen einer Void-Methode ist es wichtig, das Verarbeitungsergebnis zu überprüfen. Wenn Sie beispielsweise eine Datenbank oder Datei verarbeiten, bestätigen Sie das Ergebnis. Überprüfen Sie im Fall der Sample-Klasse, ob die an die Konsole ausgegebene Zeichenfolge korrekt ist. Zum Beispiel so.

//Standardausgabeergebnisumleitung
ByteArrayOutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
//Getesteter Anruf
this.doStaticPrivateMethod("dispMessage", null, null);
//Behaupten
assertEquals("Hello world!" + System.lineSeparator(),  out.toString());

Wenn Sie das Beispiel ausführen möchten, importieren Sie ByteArrayOutputStream und PrintStream.

4. Auf Ausnahmen prüfen

Alle Aufruffehler werden mit ** InvocationTargetException ** umbrochen und ausgelöst. Daher wird die Prüfung auf im Testziel ausgelöste Ausnahmen durchgeführt, indem der von InvocationTargetException umschlossene Inhalt extrahiert wird. Wenn ein Test bestätigt, dass eine Ausnahme ausgelöst wird, wenn die Ausnahme nicht ausgelöst wird oder wenn eine andere Ausnahme als die beabsichtigte Ausnahme auftritt, schlägt der Test in JUnit fehl, sodass ** fehlschlagen (explizit ** fehlschlagen) );**Anruf.

SampleTest.java


import static org.junit.Assert.*;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;

public class SampleTest {
	@Test
	public void test_setValue() throws Exception {
		try {
			Sample testee = new Sample("test");
			this.doPrivateMethod(
					testee, "setValue", new Class[]{String.class}, new Object[]{""});
			//Im Test durchgefallen
			fail();
		} catch (InvocationTargetException e) {
			//Ausnahmetypprüfung
			assertTrue(e.getCause() instanceof IllegalArgumentException);
			//Überprüfung der Ausnahmemeldung
			assertEquals("argument is empty.", e.getCause().getMessage());
		} catch (Exception e) {
			//Im Test durchgefallen
			fail(e.getMessage());
		}
	}
}

5. Rufen Sie den privaten Konstruktor auf

Schreibt es nicht einen privaten Konstruktor ohne Argumente, um zu verhindern, dass er in einer statischen Klasse von außen aufgerufen wird? Das ist die Testmethode. Es wird in Projekten verwendet, bei denen "100% Deckung" eine Bedingung ist. Der Kommentar lautet "Schreiben Sie den Klassennamen mit einem vollständig qualifizierten Namen". Da die Beispielklasse diesmal nicht gepackt ist, wird nur der Klassenname beschrieben. Normalerweise denke ich, dass es ein Paket gibt, daher funktioniert es nur, wenn es sich um einen vollständig qualifizierten Namen handelt.

SampleTest.java


import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.*;

import java.lang.reflect.Constructor;
import org.junit.Test;

public class SampleTest {
	@Test
	public void test_private_constructor() {
		try {
			//Beschreiben Sie den Klassennamen als vollständig qualifizierten Namen
			Class<?> clazz = Class.forName("Sample");
			Constructor<?>[] constructors = clazz.getDeclaredConstructors();
			constructors[1].setAccessible(true);
			Object obj = constructors[1].newInstance();
			assertNotNull(obj);
			assertThat(obj, instanceOf(clazz));
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}

constructors[1].setAccessible(true);

Beschreiben Sie hier die in der Beispielklasse mit 0-Ursprung beschriebene Reihenfolge. In diesem Fall ist der private Konstruktor, den Sie testen möchten, der zweite der Sample-Klassenkonstruktoren, daher ist er "1". Wenn Sie nur einen Konstruktor zum Testen haben, ist "0" in Ordnung.


Hab ein gutes Java-Leben! Wenn etwas passiert, schreibe ich es in ein Postskriptum oder einen anderen Artikel.

Recommended Posts

[Java] Testen Sie private Methoden mit JUnit
Testen Sie private Methoden in JUnit
Testen Sie private Methoden in JUnit
So testen Sie den privaten Bereich mit JUnit
Einführung eines automatisierten Java-Tests mit JUnit 5 + Gradle
Machen Sie einen Unit-Test mit Junit.
[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
Mischen Sie Testfälle mit JUnit 5 und Standardmethoden
So testen Sie eine private Methode, die ein Array- oder Argument variabler Länge in JUnit verwendet
[Java] JUnit4-Testfallbeispiel
Testen Sie die Web-API mit junit
Überprüfen Sie die private Methode der Java9-Schnittstelle
Java-Methoden
Java-Methoden
Testen Sie den Spring Framework Controller mit Junit
[Java] Ich möchte Standardeingabe und Standardausgabe mit JUnit testen
Steuern Sie die Testreihenfolge in Junit4 mit einem Aufzählungstyp
Java EE Test (CDI / Interceptor) mit Arquillian
Mit dem effektiven privaten Java-Konstruktor nicht unveränderlich erzwingen
Der JUnit 5-Gradle-Test führt zu einem Fehler mit der Lombok-Annotation
Primzahlbeurteilung Java
Java-Klassenmethoden
So testen Sie Interrupts während Thread.sleep mit JUnit
Erstellen und testen Sie Java + Gradle-Anwendungen mit Wercker
Einfacher JUnit-Test der Elasticsearch 2018-Version mit Embedded-Elasticsearch
Erstellen Sie eine E2E-Testumgebung mit Selenium (Java).
[Java] Hallo Welt mit Java 14 x Spring Boot 2.3 x JUnit 5 ~
Testcode mit Mock mit JUnit (EasyMock Center)
Visualisieren Sie die in TestNG ausgeführte Testmethode im Listener
So greifen Sie auf Java Private-Methoden und -Felder zu
Installieren Sie Java mit Homebrew
JUnit Teststart versuchen Sie etwas
Integrationstest mit Gradle
Installieren Sie Java mit Ansible
Führen Sie Maven unter Java 8 aus, während Sie unter Java 6 kompilieren und unter Java 11 testen
[JUnit 5-kompatibel] Schreiben Sie einen Test mit JUnit 5 mit Spring Boot 2.2, 2.3
Bequemer Download mit JAVA
Einfaches Memo von JUnit of Java
Java bezahlte private Memo
[Java] Verweisen Sie auf und setzen Sie private Variablen mit Reflektion
Java Unit Test Library-Arterien-Probe
Schalten Sie Java mit direnv
[Schienen] Test mit RSpec
Testen Sie Nokogiri mit Rspec.
Web-API-Komponententest und Integrationstest mit SpringBoot + Junit5, 4 Muster
Java-Download mit Ansible
Automatisch mit Messgerät testen
Lasttest mit JMeter
Lass uns mit Java kratzen! !!
Ich habe jetzt einen Test mit Spring Boot + JUnit 5 geschrieben
Erstellen Sie Java mit Wercker
Über Java-Kapselung privat öffentlich
Endian-Konvertierung mit JAVA
Beachten Sie beim Testen privater Methoden in JUnit
Ich habe Randoop untersucht, einen JUnit-Testklassengenerator für Java.
(Java) Einfache BDD mit Spektrum?
Verwenden Sie Lambda-Ebenen mit Java