JUnit

JUnit #

@Testing

Allgemeines #

Unit testing kann sich beziehen auf

  • eine Methode,
  • eine Gruppe von Methoden oder
  • eine Klasse

Test-Methoden sollten immer public sein, da möglicherweise ein externes Framework darauf zugreifen muss.

@BeforeClass- und @AfterClass-Methoden müssen immer static sein.

Exceptions testen. Bspw.: @Test(expected=NullPointerException.class) public void testArraySort_NullArray() { int[] numbers = {}; Arrays.sort(numbers); }

Performance Testing mit JUnit. Bspw.: @Test(timeout=1000) public void testSort_Performance(){ int array[] = {12,23,4}; for(int i=1; i<100000;i++) { array[0] = i; Arrays.sort(array); } }

Es macht Sinn, das Timeout nicht zu eng zu setzen, da die Tests auch in anderen Umgebungen (bspw. Testserver) ausgeführt werden, die möglicherweise ein anderes Hardware-Setting haben.

Parametrisierte Klassen werden verwendet, wenn die Test-Logik dieselbe ist, aber verschiedene Ein- und Rückgabewerte getestet werden sollen

  • Test-Klasse muss mit @RunWith(Parametrized.class) annotiert werden
  • Eine statische Methode, welche mit @Parameters annotiert ist und eine Collection<> zurückgibt (als Map mit Ein- und Rückgabe-Wert)
  • Ein Constructor, welcher als Parameter einen Eingabewert und den zugehörigen erwarteten Rückgabe-Wert entgegennimmt und diese Klassen-Members übergibt
  • Verwendung der entsprechenden Klassen-Members in den @Test-Methoden

Bsp.: @RunWith(Parametrized.class) public class StringHelperParametrizedTest { StringHelper helper = new StringHelper();

private String input;
private String expectedOutput;

public StringHelperParametrizedTest(String input, String expectedOutput) {
this.input = input;
this.expectedOutput = expectedOutput;
}

@Parameters
public static Collection<String[]> testCondition() {
String expectedOutputs[][] = {
{ "AAD", "CD" },
{ "ACD", "CD"  } };
return Arrays.asList(expectedOutputs);
}

@Test
public void testTruncateAInFirst2Positions() {
assertEquals(expectedOutput, helper.truncatedAInFirst2Positions(input));
}
}

Test Suites (Gruppe von Tests) sind Klassen, welche mit zwei Annotationen ausgestattet sind:

  • @RunWith(Suite.class) (stellt @SuiteClasses zur Verfügung)
  • @SuiteClasses( {<erste_testklasse.class>, <zweite_testklasse.class> etc.}}

@Rule: Anstelle von @RunWith(...), bspw. @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); Vorteil ist, dass mehrere Rules definiert werden können (im Gegenteil zu Runners). Es ist zu erwarten, dass Runners in zukünftigen Versionen von JUnit zugunsten von Rules an Wichtigkeit verlieren.

JUnit 5 #

JUnit 5 ist die aktuelle Version von JUnit und bringt gegenüber ihren Vorgängern einige tiefgreifende Änderungen mit sich. Wichtig ist dabei v.a. die Modularisierung des Frameworks: JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

  • Die Platform dienst als Fundament für das Starten von Testframeworks auf der JVM.
  • Jupiter ist die Kombination des neuen Programmierungs- und des neuen Erweiterungsmodels, um Tests und Erweiterungen zu schreiben.
  • Vintage stellt eine TestEngine zur Verfügung, um Tests auszuführen, die auf JUnit 3 oder 4 beruhen.