Für den Fall, dass Sie wirklich private Methoden in JUnit testen müssen. Ich vergesse, wie man es regelmäßig implementiert, deshalb werde ich es nie vergessen, wenn ich es fest in den Artikel geschrieben habe. Ich werde es mit dem Motiv aufschreiben.
Stellen Sie sich eine Klasse mit einer privaten Methode wie der folgenden vor.
public class MyClass {
private String introduceMyself(String name){
return "my name is " + name + ".";
}
}
Das Testen der privaten Methode IntroduMyself von MyClass kann wie folgt mithilfe von Reflection durchgeführt werden:
import com.example.MyClass;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.assertj.core.api.Assertions.assertThat;
public class MyClassTest {
@Test
void testIntroduceMyself01() throws Exception {
MyClass targetClass = new MyClass();
//Informieren Sie sich über die zu testende Methode
Method method = MyClass.class.getDeclaredMethod("introduceMyself", String.class);
//Entfernen Sie die Zugriffsbeschränkungen für Methoden
method.setAccessible(true);
//Methodenaufruf
String selfIntroduction = (String) method.invoke(targetClass,"John");
//Bestätigen Sie das Ergebnis
assertThat(selfIntroduction).isEqualTo("my name is John.");
}
}
Das Obige ist für normale Testfälle in Ordnung, aber seien Sie vorsichtig, wenn eine Ausnahme von einer privaten Methode ausgelöst wird.
Ausnahmen, die innerhalb von Method # invoke auftreten, werden in die InvocationTargetException-Klasse eingeschlossen. Daher ist es erforderlich, die Ursachenausnahme zu extrahieren, bevor eine Aussage getroffen wird.
public class MyClass {
private String introduceMyself(String name){
//Löst eine Ausnahme aus, wenn das Argument leer ist
if(name.isEmpty()){
throw new IllegalArgumentException("argument must not be empty.");
}
return "my name is " + name + ".";
}
}
public class MyClassTest {
@Test
void testIntroduceMyself02() throws Exception {
MyClass targetClass = new MyClass();
Method method = MyClass.class.getDeclaredMethod("introduceMyself", String.class);
method.setAccessible(true);
try {
method.invoke(targetClass, "");
fail("this code should not has been reached.");
}catch (InvocationTargetException e) {
//Bestätigen Sie nach dem Abrufen der Ursachenausnahme mit getCause
assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
}
}
}
Wenn Sie null als Argument für die Methode übergeben möchten, die durch Reflektion aufgerufen werden soll, müssen Sie ein Object-Array übergeben, das null als Element enthält. Seien Sie also auch hier vorsichtig.
method.invoke(targetClass, new Object[]{null});
//Das ist nicht gut
method.invoke(targetClass, null);
Wie ich bereits sagte, sollten private Methoden grundsätzlich nicht einheitlich getestet werden.
Die private Methode ist sozusagen ein interner Prozess, der von der öffentlichen (geschützten) Methode abgeschnitten ist. Durch das erzwungene Testen der internen Verarbeitung mit Reflexion wird der Testcode von der internen Implementierung abhängig, die beim Refactoring oder Hinzufügen von Funktionen zu einem Hindernis wird.
Die Vollständigkeit kann über die aufrufende Methode getestet werden, wenn es sich um eine gut konzipierte private Methode handelt.
Summary-Reflection ist erforderlich, um eine private Methode aufzurufen. Um eine Ausnahme zu testen, getCause from InvocationTargetException. Wenn Sie null zum Aufrufen übergeben, übergeben Sie ein Object-Array, das null als Element enthält. Wenn Sie eine private Methode testen müssen , Überprüfen Sie das Design-In-Prinzip sollten private Methoden über die aufrufende Methode getestet werden.