JUnit5 Anleitung

JUnit5 Anleitung

In diesem JUnit-Tutorial werden wir die Grundlagen von JUnit5 und seine neuen Funktionen anhand von Beispielen vorstellen. In der Java-Welt ist JUnit eines der beliebtesten Frameworks zur Implementierung von Unit-Tests gegen Java-Code. JUnit hilft in erster Linie Entwicklern, ihren Code selbst auf der JVM zu testen.

JUnit5-Architektur

JUnit-Plattform

  • Startet Test-Frameworks auf der JVM
  • Bietet eine TestEngine-API zur Entwicklung eines Test-Frameworks, das auf der JUnit-Plattform ausgeführt wird

JUnit Jupiter

  • Kombination aus neuem Programmiermodell zum Schreiben von Tests und Erweiterungsmodell für Erweiterungen
  • Hinzufügung neuer Annotationen wie @BeforeEach, @AfterEach, @AfterAll, @BeforeAll usw.

JUnit Vintage

  • Bietet Unterstützung zum Ausführen von früheren JUnit-Versionen 3 und 4 Tests auf dieser neuen Plattform

JUnit Maven-Abhängigkeiten

Um JUnit5-basierte Testfälle in einem Projekt zu implementieren, fügen Sie der pom.xml-Datei des Projekts folgende Abhängigkeit hinzu:

  • JUnit 5-Bibliothek
<dependency>
     <groupId>org.junit.jupiter</groupId>
     <artifactId>junit-jupiter-engine</artifactId>
     <version>5.1.1</version>
     <scope>test</scope>
</dependency>
<dependency>
     <groupId>org.junit.platform</groupId>
     <artifactId>junit-platform-runner</artifactId>
     <version> 1.1.1</version>
     <scope>test</scope>
</dependency>
  • JUnit5 Maven Surefire-Provider zum Ausführen der Unit-Tests, wenn die IDE keine Unterstützung für JUnit5 hat (wenn die IDE Unterstützung hat, ist dieser Punkt nicht erforderlich)
<plugin>
     <artifactId>maven-surefire-plugin</artifactId>
     <version>2.19.1</version>
     <dependencies>
          <dependency>
               <groupId>org.junit.platform</groupId>
               <artifactId>junit-platform-surefire-provider</artifactId>
               <version>1.0.2</version>
          </dependency>
     </dependencies>
</plugin>

Neue Funktionen von JUnit5

Es erfordert Java 8 oder höher zur Laufzeit. Aber man kann immer noch Code testen, der mit früheren Java-Versionen kompiliert wurde. Es wurden verschiedene neue Funktionen eingeführt.

JUnit Annotations

Im Folgenden sind einige häufig verwendete Annotationen aufgeführt:

Annotation Description
@Test Denotes a test method
@DisplayName Declares a custom display name for the test class or test method
@BeforeEach Denotes that the annotated method should be executed before each test method
@AfterEach Denotes that the annotated method should be executed after each test method
@BeforeAll Denotes that the annotated method should be executed before all test methods
@AfterAll Denotes that the annotated method should be executed after all test methods
@Disable Used to disable a test class or test method
@Nested Denotes that the annotated class is a nested, non-static test class
@Tag Declare tags for filtering tests
@ExtendWith Register custom extensions
package com.journaldev;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class JUnit5Sample1Test {

  @BeforeAll
  static void beforeAll() {
    System.out.println("**--- Executed once before all test methods in this class ---**");
  }

  @BeforeEach
  void beforeEach() {
    System.out.println("**--- Executed before each test method in this class ---**");
  }

  @Test
  void testMethod1() {
    System.out.println("**--- Test method1 executed ---**");
  }

  @DisplayName("Test method2 with condition")
  @Test
  void testMethod2() {
    System.out.println("**--- Test method2 executed ---**");
  }

  @Test
  @Disabled("implementation pending")
  void testMethod3() {
	  System.out.println("**--- Test method3 executed ---**");
  }

  @AfterEach
  void afterEach() {
    System.out.println("**--- Executed after each test method in this class ---**");
  }

  @AfterAll
  static void afterAll() {
    System.out.println("**--- Executed once after all test methods in this class ---**");
  }


}

Wir können die obige JUnit-Testklasse in Eclipse -> Ausführen als -> JUnit-Test ausführen.

JUnit Assertions

Jede Testmethode muss gegen die Bedingung true ausgewertet werden, indem Assertions verwendet werden, damit der Test fortgesetzt werden kann. Die Assertions von JUnit Jupiter befinden sich in der Klasse org.junit.jupiter.api.Assertions. Alle Methoden sind statisch.

Assertion Description
assertEquals(expected, actual) Fails when expected does not equal actual
assertFalse(expression) Fails when expression is not false
assertNull(actual) Fails when actual is not null
assertNotNull(actual) Fails when actual is null
assertAll() Group many assertions and every assertion is executed even if one or more of them fails
assertTrue(expression) Fails if expression is not true
assertThrows() Class to be tested is expected to throw an exception
@Test
void testAssertEqual() {
	 assertEquals("ABC", "ABC");
	 assertEquals(20, 20, "optional assertion message");
	 assertEquals(2 + 2, 4);
}

@Test
void testAssertFalse() {
	 assertFalse("FirstName".length() == 10);
	 assertFalse(10 > 20, "assertion message");
}

@Test
void testAssertNull() {
     String str1 = null;
	 String str2 = "abc";
	 assertNull(str1);
	 assertNotNull(str2);	
}

@Test
void testAssertAll() {
	 String str1 = "abc";
	 String str2 = "pqr";
	 String str3 = "xyz";
	 assertAll("numbers",
	      () -> assertEquals(str1,"abc"),
		  () -> assertEquals(str2,"pqr"),
		  () -> assertEquals(str3,"xyz")
	 );
	 // unten stehenden Code auskommentieren und jede Assert-Ausführung verstehen
     /*assertAll("numbers",
		  () -> assertEquals(str1,"abc"),
		  () -> assertEquals(str2,"pqr1"),
		  () -> assertEquals(str3,"xyz1")
	 );*/
}

@Test
void testAssertTrue() {
	 assertTrue("FirstName".startsWith("F"));
	 assertTrue(10  {
	      throw new IllegalArgumentException("Illegal Argument Exception occured");
	 });
	 assertEquals("Illegal Argument Exception occured", exception.getMessage());
}

JUnit5 Imports

Für seine Testklassen ist der Importbefehl org.junit.jupiter.api.Test erforderlich und nicht org.junit.Test. Außerdem müssen die Testmethoden nicht öffentlich und im lokalen Paket sein.

import org.junit.jupiter.api.Test;

JUnit5 Annahmen

Annahmen sind statische Methoden in der Klasse org.junit.jupiter.api.Assumptions. Sie werden einen Test nur ausführen, wenn die angegebene Bedingung erfüllt ist, andernfalls wird der Test abgebrochen. Der abgebrochene Test führt nicht zu einem Build-Fehler. Wenn eine Annahme fehlschlägt, wird org.opentest4j.TestAbortedException ausgelöst und der Test wird übersprungen.

Assumptions Description
assumeTrue Execute the body of lamda when the positive condition hold else test will be skipped
assumeFalse Execute the body of lamda when the negative condition hold else test will be skipped
assumingThat Portion of the test method will execute if an assumption holds true and everything after the lambda will execute irrespective of the assumption in assumingThat() holds
@Test
void testAssumeTrue() {
     boolean b = 'A' == 'A';
     assumeTrue(b);
     assertEquals("Hello", "Hello");
}

@Test
@DisplayName("test executes only on Saturday")
public void testAssumeTrueSaturday() {
     LocalDateTime dt = LocalDateTime.now();
     assumeTrue(dt.getDayOfWeek().getValue() == 6);
     System.out.println("further code will execute only if above assumption holds true");
}

@Test
void testAssumeFalse() {
     boolean b = 'A' != 'A';
     assumeFalse(b);
     assertEquals("Hello", "Hello");
}

@Test
void testAssumeFalseEnvProp() {
     System.setProperty("env", "prod");
     assumeFalse("dev".equals(System.getProperty("env")));
     System.out.println("further code will execute only if above assumption hold");
}

@Test
void testAssumingThat() {
     System.setProperty("env", "test");
     assumingThat("test".equals(System.getProperty("env")),
          () -> {
               assertEquals(10, 10);
               System.out.println("perform below assertions only on the test env");
               });

     assertEquals(20, 20);
     System.out.println("perform below assertions on all env");
}

JUnit Nested Testklassen

Verschachtelte Tests ermöglichen das Erstellen von verschachtelten Klassen und die Ausführung aller ihrer Testmethoden. Die inneren Klassen müssen nicht statisch sein. Einfach die inneren Klassen mit @Nested annotieren, und alle Testmethoden darin werden ausgeführt.

@BeforeAll
static void beforeAll() {
     System.out.println("**--- JUnit5Sample4Test :: beforeAll :: Executed once before all test methods ---**");
}
 
@BeforeEach
void beforeEach() {
	 System.out.println("**--- JUnit5Sample4Test :: beforeEach :: Executed before each test method ---**");
}

@AfterEach
void afterEach() {
	 System.out.println("**--- JUnit5Sample4Test :: afterEach :: Executed after each test method ---**");
}

@AfterAll
static void afterAll() {
	 System.out.println("**--- JUnit5Sample4Test :: afterAll :: Executed after all test method ---**");
}
 
     @Nested
     class InnerClass {
 
          @BeforeEach
          void beforeEach() {
               System.out.println("**--- InnerClass :: beforeEach :: Executed before each test method ---**");
          }
 
          @AfterEach
          void afterEach() {
        	   System.out.println("**--- InnerClass :: afterEach :: Executed after each test method ---**");
          }
 
          @Test
          void testMethod1() {
        	   System.out.println("**--- InnerClass :: testMethod1 :: Executed test method1 ---**");
          }
 
          @Nested
          class InnerMostClass {
 
               @BeforeEach
               void beforeEach() {
                    System.out.println("**--- InnerMostClass :: beforeEach :: Executed before each test method ---**");
               }
 
               @AfterEach
               void afterEach() {
            	    System.out.println("**--- InnerMostClass :: afterEach :: Executed after each test method ---**");
               }
 
               @Test
               void testMethod2() {
            	    System.out.println("**--- InnerMostClass :: testMethod2 :: Executed test method2 ---**");
               }
        }
    }

JUnit Testausnahme

Es gibt Situationen, in denen erwartet wird, dass Methoden unter bestimmten Bedingungen eine Ausnahme auslösen. assertThrows führt den Test fehlerhaft durch, wenn die angegebene Methode die spezifizierte Ausnahme nicht auslöst.

Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
     throw new IllegalArgumentException("Illegal Argument Exception occured");
});
assertEquals("Illegal Argument Exception occured", exception.getMessage());

JUnit Testausführung

Die Unit-Tests können auf verschiedene Arten ausgeführt werden. Zwei der Methoden sind wie folgt:

  • Verwenden Sie die Eclipse IDE Oxygen.3a (4.7.3a) Version und öffnen Sie die auszuführende Testdatei. Klicken Sie mit der rechten Maustaste auf die Datei und wählen Sie die Option „Als JUnit-Test ausführen“
  • Verwenden Sie den Befehl „mvn test“ in der Windows-Befehlszeile

Zusammenfassung

Wir haben JUnit5 und seine neuen Funktionen mit einigen Beispielen erkundet. Außerdem haben wir untersucht, wie wir JUnit-Annotationen, Assertions, Annahmen, Ausnahmen und verschachtelte Testklassen verwenden können.

Sie können das vollständige Beispielprojekt von unserem GitHub-Repository herunterladen.

Source:
https://www.digitalocean.com/community/tutorials/junit5-tutorial