This tutorial explains unit testing with JUnit with the JUnit 5 framework (JUnit Jupiter). It explains the creation of JUnit 5 tests with the Maven and Gradle build system. It demonstrates the usage of the Eclipse IDE for developing software tests with JUnit 5 but this tutorial is also valid for tools like Visual Code or IntelliJ.

1. Overview

JUnit is a popular unit-testing framework in the Java ecosystem. JUnit 5 added many new features based on the Java 8 version of the language.

This guide gives an introduction into unit testing with the JUnit framework using JUnit 5. It focus on the usage of the framework.

For further information about testing with Java see:

  • What is software testing

  • Using Maven in the Eclipse IDE

  • Using the Eclipse IDE for creating and running JUnit test

  • Using Gradle in the Eclipse IDE

  • Mockito tutorial

  • JUnit 5 extensions

  • Hamcrest Tutorial

  • AssertJ Tutorial

  • JUnit 4 tutorial

1.1. Configuration for using JUnit 5

To use JUnit 5 you have to make the libraries available for your test code. Jump to the section which is relevant to you, for example read the Maven part, if you are using Maven as build system.

Configure Maven to use JUnit 5

== Configure Maven dependencies for JUnit 5

=== Steps required to configure Maven to use JUnit5

To use JUnit5 in an Maven project, you need to:

  • Configure to use Java 11 or higher, as this is required by JUnit5

  • Configure the maven-surefire-plugin and maven-failsafe-plugin to be at version 2.22.2 so that they can run JUnit5

  • Add dependencies to the JUnit5 API and engine for your test code

=== Configure Maven

Therefore you need to adjust your pom file, similar to the following:

                                              <properties>                        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>                        <maven.compiler.source>11</maven.compiler.source>                        <maven.compiler.target>11</maven.compiler.target>                        </properties>                        <!--1 -->                        <build>                        <plugins>                        <plugin>                        <artifactId>maven-surefire-plugin</artifactId>                        <version>2.22.2</version>                        </plugin>                        <plugin>                        <artifactId>maven-failsafe-plugin</artifactId>                        <version>2.22.2</version>                        </plugin>                        </plugins>                        </build>                        <!--2 -->                        <dependencies>                        <!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-library -->                        <dependency>                        <groupId>org.junit.jupiter</groupId>                        <artifactId>junit-jupiter-api</artifactId>                        <version>5.7.2</version>                        <scope>test</scope>                        </dependency>                        <dependency>                        <groupId>org.junit.jupiter</groupId>                        <artifactId>junit-jupiter-engine</artifactId>                        <version>5.7.2</version>                        <scope>test</scope>                        </dependency>                        </dependencies>                                          

Once you have done this, you can start using JUnit5 in your Maven project for writing unit tests.

=== Update Maven settings (in case you are using the Eclipse IDE)

Right-click your pom file, select and select your project. This triggers an update of your project settings and dependencies.

Configure Gradle to use JUnit 5

== Update build.gradle file to use JUnit5

To use JUnit 5 with the Gradle build system, ensure you use at least Gradle 6.0 to avoid already fixed issues.

Modify your build.gradle file to contain at least the following entries. Your build file may contain more dependencies.

                                              plugins                        {                        id                        'java'                        }                        repositories                        {                        mavenCentral                        ()                        }                        dependencies                        {                        testImplementation                        'org.junit.jupiter:junit-jupiter:5.7.2'                        }                        test                        {                        useJUnitPlatform                        ()                                          
Configure JUnit 5 with Eclipse

If you are not using a build system and the JUnit library is not part of the classpath of your project during the creation of a new test, Eclipse prompts you to add it.

1.2. How to define a test in JUnit?

A JUnit test is a method contained in a class which is only used for testing. This is called a Test class. To mark a method as a test method, annotate it with the @Test annotation. This method executes the code under test.

The following code defines a minimal test class with one minimal test method.

                                      package                    com.vogella.junit.first                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertTrue                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    AClassWithOneJUnitTest                    {                    @Test                    void                    demoTestMethod                    ()                    {                    assertTrue                    (                    true                    );                    }                    }                                  

You can use assert methods, provided by JUnit or another assert framework, to check an expected result versus the actual result. Such statement are called asserts or assert statements.

Assert statements typically allow to define messages which are shown if the test fails. You should provide here meaningful messages to make it easier for the user to identify and fix the problem. This is especially true if someone looks at the problem, who did not write the code under test or the test code.

1.3. Example for developing a JUnit 5 test for another class

The following example defines a Java class and defines software tests for it.

Assume you have the following class which you want to test.

                                      package                    com.vogella.junit5                    ;                    public                    class                    Calculator                    {                    public                    int                    multiply                    (                    int                    a                    ,                    int                    b                    )                    {                    return                    a                    *                    b                    ;                    }                    }                                  

A test class for the above class could look like the following.

                                      package                    com.vogella.junit5                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    org.junit.jupiter.api.BeforeEach                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.RepeatedTest                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    CalculatorTest                    {                    Calculator                    calculator                    ;                    @BeforeEach                                        (1)                    void                    setUp                    ()                    {                    calculator                    =                    new                    Calculator                    ();                    }                    @Test                                        (2)                    @DisplayName                    (                    "Simple multiplication should work"                    )                                        (3)                    void                    testMultiply                    ()                    {                    assertEquals                    (                    20                    ,                    calculator                    .                    multiply                    (                    4                    ,                    5                    ),                                        (4)                    "Regular multiplication should work"                    );                                        (5)                    }                    @RepeatedTest                    (                    5                    )                                        (6)                    @DisplayName                    (                    "Ensure correct handling of zero"                    )                    void                    testMultiplyWithZero                    ()                    {                    assertEquals                    (                    0                    ,                    calculator                    .                    multiply                    (                    0                    ,                    5                    ),                    "Multiple with zero should be zero"                    );                    assertEquals                    (                    0                    ,                    calculator                    .                    multiply                    (                    5                    ,                    0                    ),                    "Multiple with zero should be zero"                    );                    }                    }                                  
1 The method annotated with @BeforeEach runs before each test
2 A method annotated with @Test defines a test method
3 @DisplayName can be used to define the name of the test which is displayed to the user
4 This is an assert statement which validates that expected and actual value is the same, if not the message at the end of the method is shown
5 @RepeatedTest defines that this test method will be executed multiple times, in this example 5 times

1.4. JUnit test class naming conventions

Build tools like Maven use a pattern to decide if a class is a test classes or not. The following is the list of classes Maven considers automatically during its build:

                  **/Test*.java                                        (1)                    **/*Test.java                                        (2)                    **/*Tests.java                                        (3)                    **/*TestCase.java                                        (4)                                  
1 includes all of its subdirectories and all Java filenames that start with Test.
2 includes all of its subdirectories and all Java filenames that end with Test.
3 includes all of its subdirectories and all Java filenames that end with Tests.
4 includes all of its subdirectories and all Java filenames that end with TestCase.

Therefore, it is common practice to use the Test or Tests suffix at the end of test classes names.

1.5. Where should the test be located?

Typical, unit tests are created in a separate source folder to keep the test code separate from the real code. The standard convention from the Maven and Gradle build tools is to use:

  • src/main/java - for Java classes

  • src/test/java - for test classes

1.6. Static imports and unit testing

JUnit 5 allows to use static imports for its assertStatements to make the test code short and easy to read. Static imports are a Java feature that allows fields and methods defined in a class as public static to be used without specifying the class in which the field is defined.

JUnit assert statements are typically defined as public static to allow the developer to write short test statements. The following snippet demonstrates an assert statement with and without static imports.

                                      // without static imports you have to write the following statement                    import                    org.junit.jupiter.api.Assertions                    ;                    // more code                    Assert                    .                    assertEquals                    (                    "10 x 5 must be 50"                    ,                    50                    ,                    tester                    .                    multiply                    (                    10                    ,                    5                    ));                    // alternatively define assertEquals as static import                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    // more code                    // use assertEquals directly because of the static import                    assertEquals                    (                    calculator                    .                    multiply                    (                    4                    ,                    5                    ),                    20                    ,                    "Regular multiplication should work"                    );                                  

2. Assertions and assumptions

JUnit 5 comes with multiple assert statements, which allows you to test your code under test. Simple assert statements like the following allow to check for true, false or equality. All of them are static methods from the org.junit.jupiter.api.Assertions.* package.

Assert statement Example

assertEquals

assertEquals(4, calculator.multiply(2, 2),"optional failure message");

assertTrue

assertTrue('a' < 'b', () → "optional failure message");

assertFalse

assertFalse('a' > 'b', () → "optional failure message");

assertNotNull

assertNotNull(yourObject, "optional failure message");

assertNull

assertNull(yourObject, "optional failure message");

Messages can be created via lambda expressions, to avoid the overhead in case the construction of the message is expensive.

                                  assertTrue                  (                  'a'                  <                  'b'                  ,                  ()                  ->                  "Assertion messages can be lazily evaluated -- "                  +                  "to avoid constructing complex messages unnecessarily."                  );                              

2.1. Testing for exceptions

Testing that certain exceptions are thrown are be done with the org.junit.jupiter.api.Assertions.expectThrows() assert statement. You define the expected Exception class and provide code that should throw the exception.

                                      import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertThrows                    ;                    @Test                    void                    exceptionTesting                    ()                    {                    // set up user                    Throwable                    exception                    =                    assertThrows                    (                    IllegalArgumentException                    .                    class                    ,                    ()                    ->                    user                    .                    setAge                    (                    "23"                    ));                    assertEquals                    (                    "Age must be an Integer."                    ,                    exception                    .                    getMessage                    ());                    }                                  

This lets you define which part of the test should throw the exception. The test will still fail if an exception is thrown outside of this scope.

2.2. Testing multiple assertions (grouped assertions) with assertAll

If an assert fails in a test, JUnit will stop executing the test and additional asserts are not checked. In case you want to ensure that all asserts are checked you can assertAll.

In this grouped assertion all assertions are executed, even after a failure. The error messages get also grouped together.

                                      @Test                    void                    groupedAssertions                    ()                    {                    Address                    address                    =                    new                    Address                    ();                    assertAll                    (                    "address name"                    ,                    ()                    ->                    assertEquals                    (                    "John"                    ,                    address                    .                    getFirstName                    ()),                    ()                    ->                    assertEquals                    (                    "User"                    ,                    address                    .                    getLastName                    ())                    );                    }                                  

If these tests fail, the result looks like the following:

                  => org.opentest4j.MultipleFailuresError: address name (2 failures) expected: <John> but was: <null> expected: <User> but was: <null>                

2.3. Defining timeouts in your tests

If you want to ensure that a test fails, if it isn't done in a certain amount of time you can use the assertTimeout() method. This assert fails the method if the timeout is exceeded.

                                      import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertTimeout                    ;                    import                    static                    java                    .                    time                    .                    Duration                    .                    ofSeconds                    ;                    import                    static                    java                    .                    time                    .                    Duration                    .                    ofMinutes                    ;                    @Test                    void                    timeoutNotExceeded                    ()                    {                    assertTimeout                    (                    ofMinutes                    (                    1                    ),                    ()                    ->                    service                    .                    doBackup                    ());                    }                    // if you have to check a return value                    @Test                    void                    timeoutNotExceededWithResult                    ()                    {                    String                    actualResult                    =                    assertTimeout                    (                    ofSeconds                    (                    1                    ),                    ()                    ->                    {                    return                    restService                    .                    request                    (                    request                    );                    });                    assertEquals                    (                    200                    ,                    request                    .                    getStatus                    ());                    }                                  
                                      =>                    org                    .                    opentest4j                    .                    AssertionFailedError                    :                    execution                    exceeded                    timeout                    of                    1000                    ms                    by                    212                    ms                                  

If you want your tests to cancel after the timeout period is passed you can use the assertTimeoutPreemptively() method.

                                      @Test                    void                    timeoutNotExceededWithResult                    ()                    {                    String                    actualResult                    =                    assertTimeoutPreemptively                    (                    ofSeconds                    (                    1                    ),                    ()                    ->                    {                    return                    restService                    .                    request                    (                    request                    );                    });                    assertEquals                    (                    200                    ,                    request                    .                    getStatus                    ());                    }                                  
                                      =>                    org                    .                    opentest4j                    .                    AssertionFailedError                    :                    execution                    timed                    out                    after                    1000                    ms                                  

Such a test might be flacky, in case the test server is busy, the test execution might take longer and therefore such a test might fails from time to time.

2.4. How to disable tests

The @Disabled or @Disabled("Why disabled") annotation marks a test to be disabled. This is useful when the underlying code has been changed and the test case has not yet been adapted of if the test demonstrates an incorrect behavior in the code which has not yet been fixed. It is best practice to provide the optional description, why the test is disabled.

Alternatively you can use Assumptions.assumeFalse or Assumptions.assumeTrue to define a condition for test execution. Assumptions.assumeFalse marks the test as invalid, if its condition evaluates to true. Assumptions.assumeTrue evaluates the test as invalid if its condition evaluates to false. For example, the following disables a test on Linux:

                                      Assumptions                    .                    assumeFalse                    (                    System                    .                    getProperty                    (                    "os.name"                    ).                    contains                    (                    "Linux"                    ));                                  

This gives TestAbortedException which the test runners evaluate as skipped tests.

For example the following testMultiplyWithZero is skipped if executed on Linux.

                                      package                    com.vogella.junit5                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    org.junit.jupiter.api.Assumptions                    ;                    import                    org.junit.jupiter.api.BeforeEach                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.RepeatedTest                    ;                    import                    org.junit.jupiter.api.Test                    ;                    public                    class                    CalculatorTest                    {                    private                    Calculator                    calculator                    ;                    @BeforeEach                    void                    setUp                    ()                    throws                    Exception                    {                    calculator                    =                    new                    Calculator                    ();                    }                    @RepeatedTest                    (                    5                    )                    @DisplayName                    (                    "Ensure correct handling of zero"                    )                    void                    testMultiplyWithZero                    ()                    {                    Assumptions                    .                    assumeFalse                    (                    System                    .                    getProperty                    (                    "os.name"                    ).                    contains                    (                    "Linux"                    ));                    assertEquals                    (                    calculator                    .                    multiply                    (                    0                    ,                    5                    ),                    0                    ,                    "Multiple with zero should be zero"                    );                    assertEquals                    (                    calculator                    .                    multiply                    (                    5                    ,                    0                    ),                    0                    ,                    "Multiple with zero should be zero"                    );                    }                    }                                  

You can also write an extension for @ExtendWith which defines conditions under which a test should run.

3. Dynamic and parameterized tests

JUnit 5 supports the creation of dynamic tests via code. You can also run tests with a set of different input values with parameterized tests.

Both approaches are described here.

3.1. Using Dynamic Tests

Dynamic test methods are annotated with @TestFactory and allow to create multiple tests of type DynamicTest with your code. They can return:

  • an Iterable

  • a Collection

  • a Stream

JUnit 5 creates and runs all dynamic tests during test execution.

Methods annotated with @BeforeEach and @AfterEach are not called for dynamic tests. This means, that you can't use thesm to reset the test object, if you change it's state in the lambda expression for a dynamic test.

In the following example we define a method to return a Stream of DynamicTest instances.

                                      package                    com.vogella.unittest                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    DynamicTest                    .                    dynamicTest                    ;                    import                    java.util.Arrays                    ;                    import                    java.util.stream.Stream                    ;                    import                    org.junit.jupiter.api.DynamicTest                    ;                    import                    org.junit.jupiter.api.TestFactory                    ;                    class                    DynamicTestCreationTest                    {                    @TestFactory                    Stream                    <                    DynamicTest                    >                    testDifferentMultiplyOperations                    ()                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    int                    [][]                    data                    =                    new                    int                    [][]                    {                    {                    1                    ,                    2                    ,                    2                    },                    {                    5                    ,                    3                    ,                    15                    },                    {                    121                    ,                    4                    ,                    484                    }                    };                    return                    Arrays                    .                    stream                    (                    data                    ).                    map                    (                    entry                    ->                    {                    int                    m1                    =                    entry                    [                    0                    ];                    int                    m2                    =                    entry                    [                    1                    ];                    int                    expected                    =                    entry                    [                    2                    ];                    return                    dynamicTest                    (                    m1                    +                    " * "                    +                    m2                    +                    " = "                    +                    expected                    ,                    ()                    ->                    {                    assertEquals                    (                    expected                    ,                    tester                    .                    multiply                    (                    m1                    ,                    m2                    ));                    });                    });                    }                    // class to be tested                    class                    MyClass                    {                    public                    int                    multiply                    (                    int                    i                    ,                    int                    j                    )                    {                    return                    i                    *                    j                    ;                    }                    }                    }                                  

3.2. Using Parameterized Tests

Junit5 also supports parameterized tests. To use them you have to add the junit-jupiter-params package as a test dependencies.

Adding junit-jupiter-params dependency for a Maven build
                                          <dependency>                      <groupId>org.junit.jupiter</groupId>                      <artifactId>junit-jupiter-params</artifactId>                      <version>5.7.2</version>                      <scope>test</scope>                      </dependency>                                      
Adding junit-jupiter-params dependency for a Gradle build

If you are using Gradle:

                                              dependencies                        {                        // .. your other dependencies                        testImplementation                        'org.junit.jupiter:junit-jupiter-params:5.7.2'                        }                                          

For this example we use the @MethodSource annotation.

We give it the name of the function(s) we want it to call to get it's test data. The function has to be static and must return either a Collection, an Iterator, a Stream or an Array. On execution the test method gets called once for every entry in the data source. In contrast to Dynamic Tests @BeforeEach and @AfterEach methods will be called for parameterized tests.

                                      import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .*;                    import                    org.junit.jupiter.params.ParameterizedTest                    ;                    import                    org.junit.jupiter.params.provider.MethodSource                    ;                    public                    class                    UsingParameterizedTest                    {                    public                    static                    int                    [][]                    data                    ()                    {                    return                    new                    int                    [][]                    {                    {                    1                    ,                    2                    ,                    2                    },                    {                    5                    ,                    3                    ,                    15                    },                    {                    121                    ,                    4                    ,                    484                    }                    };                    }                    @ParameterizedTest                    @MethodSource                    (                    value                    =                    "data"                    )                    void                    testWithStringParameter                    (                    int                    []                    data                    )                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    int                    m1                    =                    data                    [                    0                    ];                    int                    m2                    =                    data                    [                    1                    ];                    int                    expected                    =                    data                    [                    2                    ];                    assertEquals                    (                    expected                    ,                    tester                    .                    multiply                    (                    m1                    ,                    m2                    ));                    }                    // class to be tested                    class                    MyClass                    {                    public                    int                    multiply                    (                    int                    i                    ,                    int                    j                    )                    {                    return                    i                    *                    j                    ;                    }                    }                    }                                  

3.2.1. Data sources

The following table gives an overview of all possible test data sources for parameterized tests.

Table 1. Table Parameterized Tests Data Sources
Annotation Description
                                                          @ValueSource                              (                              ints                              =                              {                              1                              ,                              2                              ,                              3                              })                                                      

Lets you define an array of test values. Permissible types are String, int, long, or double.

                                                          @EnumSource                              (                              value                              =                              Months                              .                              class                              ,                              names                              =                              {                              "JANUARY"                              ,                              "FEBRUARY"                              })                                                      

Lets you pass Enum constants as test class. With the optional attribute names you can choose which constants should be used. Otherwise all attributes are used.

                                                          @MethodSource                              (                              names                              =                              "genTestData"                              )                                                      

The result of the named method is passed as argument to the test.

                                                          @CsvSource                              ({                              "foo, 1"                              ,                              "'baz, qux', 3"                              })                              void                              testMethod                              (                              String                              first                              ,                              int                              second                              )                              {                                                      

Expects strings to be parsed as Csv. The delimiter is ','.

                                                          @ArgumentsSource                              (                              MyArgumentsProvider                              .                              class                              )                                                      

Specifies a class that provides the test data. The referenced class has to implement the ArgumentsProvider interface.

3.2.2. Argument conversion

JUnit tries to automatically convert the source strings to match the expected arguments of the test method.

If you need explicit conversion you can specify a converter with the @ConvertWith annotation. To define your own converter you have to implement the ArgumentConverter interface. In the following example we use the abstract SimpleArgumentConverter base class.

                                          @ParameterizedTest                      @ValueSource                      (                      ints                      =                      {                      1                      ,                      12                      ,                      42                      })                      void                      testWithExplicitArgumentConversion                      (                      @ConvertWith                      (                      ToOctalStringArgumentConverter                      .                      class                      )                      String                      argument                      )                      {                      System                      .                      err                      .                      println                      (                      argument                      );                      assertNotNull                      (                      argument                      );                      }                      static                      class                      ToOctalStringArgumentConverter                      extends                      SimpleArgumentConverter                      {                      @Override                      protected                      Object                      convert                      (                      Object                      source                      ,                      Class                      <?>                      targetType                      )                      {                      assertEquals                      (                      Integer                      .                      class                      ,                      source                      .                      getClass                      (),                      "Can only convert from Integers."                      );                      assertEquals                      (                      String                      .                      class                      ,                      targetType                      ,                      "Can only convert to String"                      );                      return                      Integer                      .                      toOctalString                      ((                      Integer                      )                      source                      );                      }                      }                                      

4. Additional information about JUnit 5 usage

4.1. Nested tests

The @Nested annotation can be used to annotate inner classes which also contain tests. This allows to group tests and have additional @BeforeEach method, and one @AfterEach methods. When you add nested test classes to our test class, the following rules must be followed:

  • All nested test classes must be non-static inner classes.

  • The nested test classes are annotated with @Nested annotation so that the runtime can recognize the nested test classes.

  • a nested test class can contain Test methods, one @BeforeEach method, and one @AfterEach method.

Because Java doesn't allow static members in inner classes, a nested class cannot have additional @BeforeAll and @AfterAll methods. There is no limit for the depth of the class hierarchy.

4.2. Test execution order

JUnit runs test methods is a deterministic but unpreditable order (MethodSorters.DEFAULT). You can use the @TestMethodOrder on the class to control the execution order of the tests, via:

  • @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - Allows to use the @Order(int) annotation on methods to define order

  • @TestMethodOrder(MethodOrderer.DisplayName.class) - runs test method in alphanumeric order of display name

  • @TestMethodOrder(MethodOrderer.MethodName.class) - runs test method in alphanumeric order of method name

  • Custom implementation - Implement your own MethodOrderer via the orderMethods method, which allows you to call context.getMethodDescriptors().sort(..)

The following demonstrates this with OrderAnnotation.class.

                                      package                    com.vogella.unittest.sortmethods                    ;                    import                    org.junit.jupiter.api.MethodOrderer.OrderAnnotation                    ;                    import                    org.junit.jupiter.api.Order                    ;                    import                    org.junit.jupiter.api.Test                    ;                    import                    org.junit.jupiter.api.TestMethodOrder                    ;                    @TestMethodOrder                    (                    OrderAnnotation                    .                    class                    )                    class                    OrderAnnotationDemoTest                    {                    @Test                    @Order                    (                    1                    )                    void                    firstOne                    ()                    {                    // test something here                    }                    @Test                    @Order                    (                    2                    )                    void                    secondOne                    ()                    {                    // test something here                    }                    }                                  

4.3. Using the @TempDir annotation to create temporary files and paths

The @TempDir annotations allows to annotate non-private fields or method parameters in a test method of type Path or File. JUnit 5 has registered a `ParameterResolutionException for this annotation and will create temporary files and paths for the tests. It will also remove the temporary files are each test.

                                      @Test                    @DisplayName                    (                    "Ensure that two temporary directories with same files names and content have same hash"                    )                    void                    hashTwoDynamicDirectoryWhichHaveSameContent                    (                    @TempDir                    Path                    tempDir                    ,                    @TempDir                    Path                    tempDir2                    )                    throws                    IOException                    {                    Path                    file1                    =                    tempDir                    .                    resolve                    (                    "myfile.txt"                    );                    List                    <                    String                    >                    input                    =                    Arrays                    .                    asList                    (                    "input1"                    ,                    "input2"                    ,                    "input3"                    );                    Files                    .                    write                    (                    file1                    ,                    input                    );                    assertTrue                    (                    Files                    .                    exists                    (                    file1                    ),                    "File should exist"                    );                    Path                    file2                    =                    tempDir2                    .                    resolve                    (                    "myfile.txt"                    );                    Files                    .                    write                    (                    file2                    ,                    input                    );                    assertTrue                    (                    Files                    .                    exists                    (                    file2                    ),                    "File should exist"                    );                    }                                  

4.4. Test Suites

The 5.8 release of JUnit 5 is planned to have test suite support included.

                                      import                    org.junit.platform.suite.api.SelectPackages                    ;                    import                    org.junit.platform.suite.api.Suite                    ;                    import                    org.junit.platform.suite.api.SuiteDisplayName                    ;                    @Suite                    @SuiteDisplayName                    (                    "JUnit Platform Suite Demo"                    )                    @SelectPackages                    (                    "example"                    )                    public                    class                    SuiteDemo                    {                    }                                  

5. Exercise: Writing a JUnit 5 test with Maven and Eclipse in 5 mins

In this exercise you learn you to write a JUnit5 test using Maven and the Eclipse IDE.

5.1. Project creation

Create a new Maven project with the following settings:

  • Group: com.vogella

  • Artifact: com.vogella.junit.first

  • Version: 0.0.1-SNAPSHOT

  • Packaging: jar

5.2. Configure Maven dependencies for JUnit 5

5.2.1. Steps required to configure Maven to use JUnit5

To use JUnit5 in an Maven project, you need to:

  • Configure to use Java 11 or higher, as this is required by JUnit5

  • Configure the maven-surefire-plugin and maven-failsafe-plugin to be at version 2.22.2 so that they can run JUnit5

  • Add dependencies to the JUnit5 API and engine for your test code

5.2.2. Configure Maven

Therefore you need to adjust your pom file, similar to the following:

                                          <properties>                      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>                      <maven.compiler.source>11</maven.compiler.source>                      <maven.compiler.target>11</maven.compiler.target>                      </properties>                      <!--1 -->                      <build>                      <plugins>                      <plugin>                      <artifactId>maven-surefire-plugin</artifactId>                      <version>2.22.2</version>                      </plugin>                      <plugin>                      <artifactId>maven-failsafe-plugin</artifactId>                      <version>2.22.2</version>                      </plugin>                      </plugins>                      </build>                      <!--2 -->                      <dependencies>                      <!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-library -->                      <dependency>                      <groupId>org.junit.jupiter</groupId>                      <artifactId>junit-jupiter-api</artifactId>                      <version>5.7.2</version>                      <scope>test</scope>                      </dependency>                      <dependency>                      <groupId>org.junit.jupiter</groupId>                      <artifactId>junit-jupiter-engine</artifactId>                      <version>5.7.2</version>                      <scope>test</scope>                      </dependency>                      </dependencies>                                      

Once you have done this, you can start using JUnit5 in your Maven project for writing unit tests.

5.2.3. Update Maven settings (in case you are using the Eclipse IDE)

Right-click your pom file, select and select your project. This triggers an update of your project settings and dependencies.

5.3. Package creation

Create a package named com.vogella.junit.first in the src/main/java and src/main/test folder.

5.4. Create a Java class

In the src folder, create the following class in the com.vogella.junit.first package.

                                      package                    com.vogella.junit.first                    ;                    public                    class                    MyClass                    {                    // the following is just an example                    public                    int                    multiply                    (                    int                    x                    ,                    int                    y                    )                    {                    if                    (                    x                    >                    999                    )                    {                    throw                    new                    IllegalArgumentException                    (                    "X should be less than 1000"                    );                    }                    return                    x                    /                    y                    ;                    }                    }                                  

5.5. Create a JUnit test

Position the cursor on the MyClass in the Java editor and press Ctrl+1. Select that you want to create a new JUnit test from the list.

Create new test class

Alternatively you can right-click on your new class in the :_Project Explorer_ or Package Explorer view and select .

In the following wizard ensure that the New JUnit Jupiter test flag is selected. The source folder should select the test directory.

Create new test class

Press the Next button and select the methods that you want to test.

Selecting the methods to test

Create a test with the following code.

                                      package                    com.vogella.junit.first                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertAll                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertThrows                    ;                    import                    org.junit.jupiter.api.BeforeEach                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    MyClassTest                    {                    @Test                    void                    testExceptionIsThrown                    ()                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    assertThrows                    (                    IllegalArgumentException                    .                    class                    ,                    ()                    ->                    tester                    .                    multiply                    (                    1000                    ,                    5                    ));                    }                    @Test                    void                    testMultiply                    ()                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    assertEquals                    (                    50                    ,                    tester                    .                    multiply                    (                    10                    ,                    5                    ),                    "10 x 5 must be 50"                    );                    }                    }                                  

5.6. Run your test in Eclipse

Right-click on your new test class and select .

Run JUnit test in Eclipse

The result of the tests are displayed in the JUnit view. In our example one test should be successful and one test should show an error. This error is indicated by a red bar.

Result of running a unit test

You discovered a bug in the tested code!

5.7. Fix the bug and re-run your tests

The test is failing, because our multiplier class is currently not working correctly. It does a division instead of multiplication. Fix the bug and re-run the test to get a green bar.

Solution
                                          package                      com.vogella.junit.first                      ;                      public                      class                      MyClass                      {                      // the following is just an example                      public                      int                      multiply                      (                      int                      x                      ,                      int                      y                      )                      {                      if                      (                      x                      >                      999                      )                      {                      throw                      new                      IllegalArgumentException                      (                      "X should be less than 1000"                      );                      }                      return                      x                      *                      y                      ;                      }                      }                                      

5.8. Review

After a few minutes you should have created a new project, a new class and a new unit test. Congratulations! If you feel like it, lets improve the tests a bit and write one grouped test.

5.9. Simplify your test code with @Before each

The initialization of MyClass happens in every test, move the initialization to a @BeforeEach method.

Solution
                                          import                      org.junit.jupiter.api.BeforeEach                      ;                      // more import statements                      class                      MyClassTest                      {                      private                      MyClass                      tester                      ;                      @BeforeEach                      void                      setup                      ()                      {                      tester                      =                      new                      MyClass                      ();                      }                      // tests are before                      }                                      

5.10. Define a group check with assertAll

Define a new test method which checks both condition at the same time with assertAll statement. Change the condition to make both tests fail, run the test and ensure that both are executed.

junit80

Solution
                                          @Test                      public                      void                      testGrouped                      ()                      {                      assertAll                      (                      //                      ()                      ->                      assertThrows                      (                      IllegalArgumentException                      .                      class                      ,                      ()                      ->                      tester                      .                      multiply                      (                      1                      ,                      5                      )),                      ()                      ->                      assertEquals                      (                      501                      ,                      tester                      .                      multiply                      (                      10                      ,                      5                      ),                      "10 x 5 must be 50"                      )                      );                      }                                      

Afterwards adjust the test so that both are successfully executed.

6. Exercise: Writing a JUnit 5 test with Gradle and Eclipse in 5 mins

In this exercise you learn you to write a JUnit5 test using the Gradle build system and the Eclipse IDE.

6.1. Project creation

Create a new Gradle project with the following setting:

  • Name: com.vogella.junit.first

The wizard should also have create the package com.vogella.junit.first in the src/main/java and src/main/test folder. Remove the generated classes from it.

6.2. Update build.gradle file to use JUnit5

To use JUnit 5 with the Gradle build system, ensure you use at least Gradle 6.0 to avoid already fixed issues.

Modify your build.gradle file to contain at least the following entries. Your build file may contain more dependencies.

                                      plugins                    {                    id                    'java'                    }                    repositories                    {                    mavenCentral                    ()                    }                    dependencies                    {                    testImplementation                    'org.junit.jupiter:junit-jupiter:5.7.2'                    }                    test                    {                    useJUnitPlatform                    ()                                  

6.3. Create a Java class

In the src folder, create the following class in the com.vogella.junit.first package.

                                      package                    com.vogella.junit.first                    ;                    public                    class                    MyClass                    {                    // the following is just an example                    public                    int                    multiply                    (                    int                    x                    ,                    int                    y                    )                    {                    if                    (                    x                    >                    999                    )                    {                    throw                    new                    IllegalArgumentException                    (                    "X should be less than 1000"                    );                    }                    return                    x                    /                    y                    ;                    }                    }                                  

6.4. Create a JUnit test

Position the cursor on the MyClass in the Java editor and press Ctrl+1. Select that you want to create a new JUnit test from the list.

Create new test class

Alternatively you can right-click on your new class in the :_Project Explorer_ or Package Explorer view and select .

In the following wizard ensure that the New JUnit Jupiter test flag is selected. The source folder should select the test directory.

Create new test class

Press the Next button and select the methods that you want to test.

Selecting the methods to test

Create a test with the following code.

                                      package                    com.vogella.junit.first                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertAll                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertThrows                    ;                    import                    org.junit.jupiter.api.BeforeEach                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    MyClassTest                    {                    @Test                    void                    testExceptionIsThrown                    ()                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    assertThrows                    (                    IllegalArgumentException                    .                    class                    ,                    ()                    ->                    tester                    .                    multiply                    (                    1000                    ,                    5                    ));                    }                    @Test                    void                    testMultiply                    ()                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    assertEquals                    (                    50                    ,                    tester                    .                    multiply                    (                    10                    ,                    5                    ),                    "10 x 5 must be 50"                    );                    }                    }                                  

6.5. Run your test in Eclipse

Right-click on your new test class and select .

Run JUnit test in Eclipse

The result of the tests are displayed in the JUnit view. In our example one test should be successful and one test should show an error. This error is indicated by a red bar.

Result of running a unit test

You discovered a bug in the tested code!

6.6. Fix the bug and re-run your tests

The test is failing, because our multiplier class is currently not working correctly. It does a division instead of multiplication. Fix the bug and re-run the test to get a green bar.

Solution
                                          package                      com.vogella.junit.first                      ;                      public                      class                      MyClass                      {                      // the following is just an example                      public                      int                      multiply                      (                      int                      x                      ,                      int                      y                      )                      {                      if                      (                      x                      >                      999                      )                      {                      throw                      new                      IllegalArgumentException                      (                      "X should be less than 1000"                      );                      }                      return                      x                      *                      y                      ;                      }                      }                                      

6.7. Review

After a few minutes you should have created a new project, a new class and a new unit test. Congratulations! If you feel like it, lets improve the tests a bit and write one grouped test.

6.8. Simplify your test code with @Before each

The initialization of MyClass happens in every test, move the initialization to a @BeforeEach method.

Solution
                                          import                      org.junit.jupiter.api.BeforeEach                      ;                      // more import statements                      class                      MyClassTest                      {                      private                      MyClass                      tester                      ;                      @BeforeEach                      void                      setup                      ()                      {                      tester                      =                      new                      MyClass                      ();                      }                      // tests are before                      }                                      

6.9. Define a group check with assertAll

Define a new test method which checks both condition at the same time with assertAll statement. Change the condition to make both tests fail, run the test and ensure that both are executed.

junit80

Solution
                                          @Test                      public                      void                      testGrouped                      ()                      {                      assertAll                      (                      //                      ()                      ->                      assertThrows                      (                      IllegalArgumentException                      .                      class                      ,                      ()                      ->                      tester                      .                      multiply                      (                      1                      ,                      5                      )),                      ()                      ->                      assertEquals                      (                      501                      ,                      tester                      .                      multiply                      (                      10                      ,                      5                      ),                      "10 x 5 must be 50"                      )                      );                      }                                      

Afterwards adjust the test so that both are successfully executed.

7. Exercise: Writing JUnit5 unit tests

In this exercise, you develop some JUnit 5 tests for a given data model. You already learned how to create projects with Maven or Gradle and how to add Junit5 to them.

To review this information see:

  • Create a Grade project with Eclipse

  • Adding JUnit to an project

The following description assumes that you are familiar with these steps and will not repeat them.

7.1. Create project and add JUnit5 dependencies

Create a new project called com.vogella.unittest either with Maven or with Gradle and update their settings to use JUnit5.

7.2. Create the data model used for testing

Create the com.vogella.unittest.model package and copy and paste the following classes on it.

                                      package                    com.vogella.unittest.model                    ;                    import                    java.util.Date                    ;                    public                    class                    Movie                    {                    private                    String                    title                    ;                    private                    Date                    releaseDate                    ;                    @SuppressWarnings                    (                    "unused"                    )                    private                    String                    duration                    ;                    public                    Movie                    (                    String                    title                    ,                    Date                    releaseDate                    ,                    String                    duration                    )                    {                    super                    ();                    this                    .                    title                    =                    title                    ;                    this                    .                    releaseDate                    =                    releaseDate                    ;                    this                    .                    duration                    =                    duration                    ;                    }                    public                    String                    getTitle                    ()                    {                    return                    title                    ;                    }                    public                    Date                    getReleaseDate                    ()                    {                    return                    releaseDate                    ;                    }                    @Override                    public                    int                    hashCode                    ()                    {                    final                    int                    prime                    =                    31                    ;                    int                    result                    =                    1                    ;                    result                    =                    prime                    *                    result                    +                    ((                    releaseDate                    ==                    null                    )                    ?                    0                    :                    releaseDate                    .                    hashCode                    ());                    result                    =                    prime                    *                    result                    +                    ((                    title                    ==                    null                    )                    ?                    0                    :                    title                    .                    hashCode                    ());                    return                    result                    ;                    }                    @Override                    public                    boolean                    equals                    (                    Object                    obj                    )                    {                    if                    (                    this                    ==                    obj                    )                    return                    true                    ;                    if                    (                    obj                    ==                    null                    )                    return                    false                    ;                    if                    (                    getClass                    ()                    !=                    obj                    .                    getClass                    ())                    return                    false                    ;                    Movie                    other                    =                    (                    Movie                    )                    obj                    ;                    if                    (                    releaseDate                    ==                    null                    )                    {                    if                    (                    other                    .                    releaseDate                    !=                    null                    )                    return                    false                    ;                    }                    else                    if                    (!                    releaseDate                    .                    equals                    (                    other                    .                    releaseDate                    ))                    return                    false                    ;                    if                    (                    title                    ==                    null                    )                    {                    if                    (                    other                    .                    title                    !=                    null                    )                    return                    false                    ;                    }                    else                    if                    (!                    title                    .                    equals                    (                    other                    .                    title                    ))                    return                    false                    ;                    return                    true                    ;                    }                    }                                  
                                      package                    com.vogella.unittest.model                    ;                    public                    enum                    Alignment                    {                    SUPER_EVIL                    ,                    EVIL                    ,                    NEUTRAL                    ,                    GOOD                    ,                    SUPER_GOOD                    ;                    }                                  
                                      package                    com.vogella.unittest.model                    ;                    import                    java.lang.annotation.ElementType                    ;                    import                    java.lang.annotation.Retention                    ;                    import                    java.lang.annotation.RetentionPolicy                    ;                    import                    java.lang.annotation.Target                    ;                    @Target                    (                    ElementType                    .                    TYPE                    )                    @Retention                    (                    RetentionPolicy                    .                    RUNTIME                    )                    public                    @interface                    Magical                    {                    }                                  
                                      package                    com.vogella.unittest.model                    ;                    /**  * Race in Tolkien's Lord of the Rings.  *  * @author Florent Biville  */                    public                    enum                    Race                    {                    HOBBIT                    (                    "Hobbit"                    ,                    false                    ,                    Alignment                    .                    GOOD                    ),                    MAIA                    (                    "Maia"                    ,                    true                    ,                    Alignment                    .                    GOOD                    ),                    MAN                    (                    "Man"                    ,                    false                    ,                    Alignment                    .                    NEUTRAL                    ),                    ELF                    (                    "Elf"                    ,                    true                    ,                    Alignment                    .                    GOOD                    ),                    DWARF                    (                    "Dwarf"                    ,                    false                    ,                    Alignment                    .                    GOOD                    ),                    ORC                    (                    "Orc"                    ,                    false                    ,                    Alignment                    .                    EVIL                    );                    private                    final                    String                    name                    ;                    private                    final                    boolean                    immortal                    ;                    private                    Alignment                    alignment                    ;                    Race                    (                    String                    name                    ,                    boolean                    immortal                    ,                    Alignment                    alignment                    )                    {                    this                    .                    name                    =                    name                    ;                    this                    .                    immortal                    =                    immortal                    ;                    this                    .                    alignment                    =                    alignment                    ;                    }                    public                    String                    getName                    ()                    {                    return                    name                    ;                    }                    public                    boolean                    isImmortal                    ()                    {                    return                    immortal                    ;                    }                    public                    Alignment                    getAlignment                    ()                    {                    return                    alignment                    ;                    }                    @Override                    public                    String                    toString                    ()                    {                    return                    "Race [name="                    +                    name                    +                    ", immortal="                    +                    immortal                    +                    "]"                    ;                    }                    }                                  
                                      package                    com.vogella.unittest.model                    ;                    @Magical                    public                    enum                    Ring                    {                    oneRing                    ,                    vilya                    ,                    nenya                    ,                    narya                    ,                    dwarfRing                    ,                    manRing                    ;                    }                                  
                                      package                    com.vogella.unittest.model                    ;                    public                    class                    TolkienCharacter                    {                    // public to test extract on field                    public                    int                    age                    ;                    private                    String                    name                    ;                    private                    Race                    race                    ;                    // not accessible field to test that field by field comparison does not use it                    @SuppressWarnings                    (                    "unused"                    )                    private                    long                    notAccessibleField                    =                    System                    .                    currentTimeMillis                    ();                    public                    TolkienCharacter                    (                    String                    name                    ,                    int                    age                    ,                    Race                    race                    )                    {                    this                    .                    name                    =                    name                    ;                    this                    .                    age                    =                    age                    ;                    this                    .                    race                    =                    race                    ;                    }                    public                    Race                    getRace                    ()                    {                    return                    race                    ;                    }                    public                    String                    getName                    ()                    {                    return                    name                    ;                    }                    public                    void                    setName                    (                    String                    name                    )                    {                    this                    .                    name                    =                    name                    ;                    }                    public                    void                    setAge                    (                    int                    age                    )                    {                    if                    (                    age                    <                    0                    )                    {                    throw                    new                    IllegalArgumentException                    (                    "Age is not allowed to be smaller than zero"                    );                    }                    this                    .                    age                    =                    age                    ;                    }                    @Override                    public                    int                    hashCode                    ()                    {                    final                    int                    prime                    =                    31                    ;                    int                    result                    =                    1                    ;                    result                    =                    prime                    *                    result                    +                    age                    ;                    result                    =                    prime                    *                    result                    +                    ((                    name                    ==                    null                    )                    ?                    0                    :                    name                    .                    hashCode                    ());                    result                    =                    prime                    *                    result                    +                    ((                    race                    ==                    null                    )                    ?                    0                    :                    race                    .                    hashCode                    ());                    return                    result                    ;                    }                    @Override                    public                    boolean                    equals                    (                    Object                    obj                    )                    {                    if                    (                    this                    ==                    obj                    )                    return                    true                    ;                    if                    (                    obj                    ==                    null                    )                    return                    false                    ;                    if                    (                    getClass                    ()                    !=                    obj                    .                    getClass                    ())                    return                    false                    ;                    TolkienCharacter                    other                    =                    (                    TolkienCharacter                    )                    obj                    ;                    if                    (                    age                    !=                    other                    .                    age                    )                    return                    false                    ;                    if                    (                    name                    ==                    null                    )                    {                    if                    (                    other                    .                    name                    !=                    null                    )                    return                    false                    ;                    }                    else                    if                    (!                    name                    .                    equals                    (                    other                    .                    name                    ))                    return                    false                    ;                    if                    (                    race                    ==                    null                    )                    {                    if                    (                    other                    .                    race                    !=                    null                    )                    return                    false                    ;                    }                    else                    if                    (!                    race                    .                    equals                    (                    other                    .                    race                    ))                    return                    false                    ;                    return                    true                    ;                    }                    @Override                    public                    String                    toString                    ()                    {                    return                    name                    +                    " "                    +                    age                    +                    " years old "                    +                    race                    .                    getName                    ();                    }                    }                                  

Create the com.vogella.unittest.services package and copy and paste the following classes on it.

                                      package                    com.vogella.unittest.services                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    DWARF                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    ELF                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    HOBBIT                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    MAIA                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    MAN                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    ORC                    ;                    import                    java.util.ArrayList                    ;                    import                    java.util.Date                    ;                    import                    java.util.HashMap                    ;                    import                    java.util.List                    ;                    import                    java.util.Map                    ;                    import                    com.vogella.unittest.model.Movie                    ;                    import                    com.vogella.unittest.model.Ring                    ;                    import                    com.vogella.unittest.model.TolkienCharacter                    ;                    /**  * Init data for unit test  */                    public                    class                    DataService                    {                    static                    final                    String                    ERROR_MESSAGE_EXAMPLE_FOR_ASSERTION                    =                    "{} assertion : {}\n"                    ;                    // Some of the Lord of the Rings characters :                    final                    TolkienCharacter                    frodo                    =                    new                    TolkienCharacter                    (                    "Frodo"                    ,                    33                    ,                    HOBBIT                    );                    final                    TolkienCharacter                    sam                    =                    new                    TolkienCharacter                    (                    "Sam"                    ,                    38                    ,                    HOBBIT                    );                    final                    TolkienCharacter                    merry                    =                    new                    TolkienCharacter                    (                    "Merry"                    ,                    36                    ,                    HOBBIT                    );                    final                    TolkienCharacter                    pippin                    =                    new                    TolkienCharacter                    (                    "Pippin"                    ,                    28                    ,                    HOBBIT                    );                    final                    TolkienCharacter                    gandalf                    =                    new                    TolkienCharacter                    (                    "Gandalf"                    ,                    2020                    ,                    MAIA                    );                    final                    TolkienCharacter                    gimli                    =                    new                    TolkienCharacter                    (                    "Gimli"                    ,                    139                    ,                    DWARF                    );                    final                    TolkienCharacter                    legolas                    =                    new                    TolkienCharacter                    (                    "Legolas"                    ,                    1000                    ,                    ELF                    );                    final                    TolkienCharacter                    aragorn                    =                    new                    TolkienCharacter                    (                    "Aragorn"                    ,                    87                    ,                    MAN                    );                    final                    TolkienCharacter                    boromir                    =                    new                    TolkienCharacter                    (                    "Boromir"                    ,                    37                    ,                    MAN                    );                    final                    TolkienCharacter                    sauron                    =                    new                    TolkienCharacter                    (                    "Sauron"                    ,                    50000                    ,                    MAIA                    );                    final                    TolkienCharacter                    galadriel                    =                    new                    TolkienCharacter                    (                    "Galadriel"                    ,                    3000                    ,                    ELF                    );                    final                    TolkienCharacter                    elrond                    =                    new                    TolkienCharacter                    (                    "Elrond"                    ,                    3000                    ,                    ELF                    );                    final                    TolkienCharacter                    guruk                    =                    new                    TolkienCharacter                    (                    "Guruk"                    ,                    20                    ,                    ORC                    );                    final                    Movie                    theFellowshipOfTheRing                    =                    new                    Movie                    (                    "the fellowship of the Ring"                    ,                    new                    Date                    (),                    "178 min"                    );                    final                    Movie                    theTwoTowers                    =                    new                    Movie                    (                    "the two Towers"                    ,                    new                    Date                    (),                    "179 min"                    );                    final                    Movie                    theReturnOfTheKing                    =                    new                    Movie                    (                    "the Return of the King"                    ,                    new                    Date                    (),                    "201 min"                    );                    public                    List                    <                    TolkienCharacter                    >                    getFellowship                    ()                    {                    final                    List                    <                    TolkienCharacter                    >                    fellowshipOfTheRing                    =                    new                    ArrayList                    <>();                    // let's do some team building :)                    fellowshipOfTheRing                    .                    add                    (                    frodo                    );                    fellowshipOfTheRing                    .                    add                    (                    sam                    );                    fellowshipOfTheRing                    .                    add                    (                    merry                    );                    fellowshipOfTheRing                    .                    add                    (                    pippin                    );                    fellowshipOfTheRing                    .                    add                    (                    gandalf                    );                    fellowshipOfTheRing                    .                    add                    (                    legolas                    );                    fellowshipOfTheRing                    .                    add                    (                    gimli                    );                    fellowshipOfTheRing                    .                    add                    (                    aragorn                    );                    fellowshipOfTheRing                    .                    add                    (                    boromir                    );                    return                    fellowshipOfTheRing                    ;                    }                    public                    List                    <                    TolkienCharacter                    >                    getOrcsWithHobbitPrisoners                    ()                    {                    final                    List                    <                    TolkienCharacter                    >                    orcsWithHobbitPrisoners                    =                    new                    ArrayList                    <                    TolkienCharacter                    >();                    orcsWithHobbitPrisoners                    .                    add                    (                    guruk                    );                    orcsWithHobbitPrisoners                    .                    add                    (                    merry                    );                    orcsWithHobbitPrisoners                    .                    add                    (                    pippin                    );                    return                    orcsWithHobbitPrisoners                    ;                    }                    public                    TolkienCharacter                    getFellowshipCharacter                    (                    String                    name                    )                    {                    List                    <                    TolkienCharacter                    >                    list                    =                    getFellowship                    ();                    return                    list                    .                    stream                    ().                    filter                    (                    s                    ->                    s                    .                    equals                    (                    name                    )).                    findFirst                    ().                    get                    ();                    }                    public                    Map                    <                    Ring                    ,                    TolkienCharacter                    >                    getRingBearers                    ()                    {                    Map                    <                    Ring                    ,                    TolkienCharacter                    >                    ringBearers                    =                    new                    HashMap                    <>();                    // ring bearers                    ringBearers                    .                    put                    (                    Ring                    .                    nenya                    ,                    galadriel                    );                    ringBearers                    .                    put                    (                    Ring                    .                    narya                    ,                    gandalf                    );                    ringBearers                    .                    put                    (                    Ring                    .                    vilya                    ,                    elrond                    );                    ringBearers                    .                    put                    (                    Ring                    .                    oneRing                    ,                    frodo                    );                    return                    ringBearers                    ;                    }                    }                                  

7.3. Write tests for the model and the services

Create the following test class.

                                      package                    com.vogella.unittest.services                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    HOBBIT                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertNotNull                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    fail                    ;                    import                    java.util.List                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.Tag                    ;                    import                    org.junit.jupiter.api.Test                    ;                    import                    com.vogella.unittest.model.TolkienCharacter                    ;                    import                    com.vogella.unittest.services.DataService                    ;                    class                    DataServiceTest                    {                    // TODO initialize before each test                    DataService                    dataService                    ;                    @Test                    void                    ensureThatInitializationOfTolkeinCharactorsWorks                    ()                    {                    TolkienCharacter                    frodo                    =                    new                    TolkienCharacter                    (                    "Frodo"                    ,                    33                    ,                    HOBBIT                    );                    // TODO check that age is 33                    // TODO check that name is "Frodo"                    // TODO check that name is not "Frodon"                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureThatEqualsWorksForCharaters                    ()                    {                    Object                    jake                    =                    new                    TolkienCharacter                    (                    "Jake"                    ,                    43                    ,                    HOBBIT                    );                    Object                    sameJake                    =                    jake                    ;                    Object                    jakeClone                    =                    new                    TolkienCharacter                    (                    "Jake"                    ,                    12                    ,                    HOBBIT                    );                    // TODO check that:                    // jake is equal to sameJake                    // jake is not equal to jakeClone                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    checkInheritance                    ()                    {                    TolkienCharacter                    tolkienCharacter                    =                    dataService                    .                    getFellowship                    ().                    get                    (                    0                    );                    // TODO check that tolkienCharacter.getClass is not a movie class                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureFellowShipCharacterAccessByNameReturnsNullForUnknownCharacter                    ()                    {                    // TODO imlement a check that dataService.getFellowshipCharacter returns null for an                    // unknow felllow, e.g. "Lars"                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureFellowShipCharacterAccessByNameWorksGivenCorrectNameIsGiven                    ()                    {                    // TODO imlement a check that dataService.getFellowshipCharacter returns a fellow for an                    // existing felllow, e.g. "Frodo"                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureThatFrodoAndGandalfArePartOfTheFellowsip                    ()                    {                    List                    <                    TolkienCharacter                    >                    fellowship                    =                    dataService                    .                    getFellowship                    ();                    // TODO check that Frodo and Gandalf are part of the fellowship                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureThatOneRingBearerIsPartOfTheFellowship                    ()                    {                    List                    <                    TolkienCharacter                    >                    fellowship                    =                    dataService                    .                    getFellowship                    ();                    // TODO test that at least one ring bearer is part of the fellowship                    fail                    (                    "not yet implemented"                    );                    }                    // TODO Use @RepeatedTest(int) to execute this test 1000 times                    @Test                    @Tag                    (                    "slow"                    )                    @DisplayName                    (                    "Minimal stress testing: run this test 1000 times to "                    )                    void                    ensureThatWeCanRetrieveFellowshipMultipleTimes                    ()                    {                    dataService                    =                    new                    DataService                    ();                    assertNotNull                    (                    dataService                    .                    getFellowship                    ());                    fail                    (                    "this should run 1000 times"                    );                    }                    @Test                    void                    ensureOrdering                    ()                    {                    List                    <                    TolkienCharacter                    >                    fellowship                    =                    dataService                    .                    getFellowship                    ();                    // ensure that the order of the fellowship is:                    // frodo, sam, merry,pippin, gandalf,legolas,gimli,aragorn,boromir                    fail                    (                    "not yet implemented"                    );                    }                    @Test                    void                    ensureAge                    ()                    {                    List                    <                    TolkienCharacter                    >                    fellowship                    =                    dataService                    .                    getFellowship                    ();                    // TODO test ensure that all hobbits and men are younger than 100 years                    // TODO also ensure that the elfs, dwars the maia are all older than 100 years                    fail                    (                    "not yet implemented"                    );                    // HINT fellowship.stream might be useful here                    }                    @Test                    void                    ensureThatFellowsStayASmallGroup                    ()                    {                    List                    <                    TolkienCharacter                    >                    fellowship                    =                    dataService                    .                    getFellowship                    ();                    // TODO Write a test to get the 20 element from the fellowship throws an                    // IndexOutOfBoundsException                    fail                    (                    "not yet implemented"                    );                    }                    }                                  

Solve the TODO and ensure that all tests can be successfully executed from your IDE. You may find issues in the DataService with these tests, fix them if you encounter them.

Solution

The following is a possible implementation of the tests:

                                              package                        com.vogella.unittest.services                        ;                        import                        static                        com                        .                        vogella                        .                        unittest                        .                        model                        .                        Race                        .                        HOBBIT                        ;                        import                        static                        com                        .                        vogella                        .                        unittest                        .                        model                        .                        Race                        .                        MAIA                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertEquals                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertFalse                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertNotEquals                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertNotNull                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertNull                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertThrows                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertTrue                        ;                        import                        java.util.List                        ;                        import                        java.util.Map                        ;                        import                        org.junit.jupiter.api.BeforeEach                        ;                        import                        org.junit.jupiter.api.DisplayName                        ;                        import                        org.junit.jupiter.api.RepeatedTest                        ;                        import                        org.junit.jupiter.api.Tag                        ;                        import                        org.junit.jupiter.api.Test                        ;                        import                        com.vogella.unittest.model.Movie                        ;                        import                        com.vogella.unittest.model.Race                        ;                        import                        com.vogella.unittest.model.Ring                        ;                        import                        com.vogella.unittest.model.TolkienCharacter                        ;                        import                        com.vogella.unittest.services.DataService                        ;                        class                        DataServiceTest                        {                        DataService                        dataService                        ;                        @BeforeEach                        void                        setup                        ()                        {                        dataService                        =                        new                        DataService                        ();                        }                        @Test                        void                        ensureThatInitializationOfTolkeinCharactorsWorks                        ()                        {                        TolkienCharacter                        frodo                        =                        new                        TolkienCharacter                        (                        "Frodo"                        ,                        33                        ,                        HOBBIT                        );                        assertEquals                        (                        33                        ,                        frodo                        .                        age                        ,                        "Frodo should be 33"                        );                        assertEquals                        (                        "Frodo"                        ,                        frodo                        .                        getName                        (),                        "Frodos character has wrong name"                        );                        assertNotEquals                        (                        "Frodon"                        ,                        frodo                        .                        getName                        (),                        "Frodos character has wrong name"                        );                        }                        @Test                        void                        ensureFellowShipCharacterAccessByNameReturnsNullForUnknownCharacter                        ()                        {                        TolkienCharacter                        fellowshipCharacter                        =                        dataService                        .                        getFellowshipCharacter                        (                        "Lars"                        );                        assertNull                        (                        fellowshipCharacter                        );                        }                        @Test                        void                        ensureFellowShipCharacterAccessByNameWorksGivenCorrectNameIsGiven                        ()                        {                        TolkienCharacter                        fellowshipCharacter                        =                        dataService                        .                        getFellowshipCharacter                        (                        "Frodo"                        );                        assertNotNull                        (                        fellowshipCharacter                        );                        }                        @Test                        void                        ensureThatEqualsWorksForCharaters                        ()                        {                        Object                        jake                        =                        new                        TolkienCharacter                        (                        "Jake"                        ,                        43                        ,                        HOBBIT                        );                        Object                        sameJake                        =                        jake                        ;                        Object                        jakeClone                        =                        new                        TolkienCharacter                        (                        "Jake"                        ,                        12                        ,                        HOBBIT                        );                        assertEquals                        (                        jake                        ,                        sameJake                        );                        assertNotEquals                        (                        jake                        ,                        jakeClone                        );                        }                        @Test                        void                        checkInheritance                        ()                        {                        TolkienCharacter                        tolkienCharacter                        =                        dataService                        .                        getFellowship                        ().                        get                        (                        0                        );                        assertFalse                        (                        Movie                        .                        class                        .                        isAssignableFrom                        (                        tolkienCharacter                        .                        getClass                        ()));                        assertTrue                        (                        TolkienCharacter                        .                        class                        .                        isAssignableFrom                        (                        tolkienCharacter                        .                        getClass                        ()));                        }                        @Test                        void                        ensureThatFrodoAndGandalfArePartOfTheFellowsip                        ()                        {                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        TolkienCharacter                        frodo                        =                        new                        TolkienCharacter                        (                        "Frodo"                        ,                        33                        ,                        HOBBIT                        );                        TolkienCharacter                        gandalf                        =                        new                        TolkienCharacter                        (                        "Gandalf"                        ,                        2020                        ,                        MAIA                        );                        assertTrue                        (                        fellowship                        .                        contains                        (                        frodo                        ));                        assertTrue                        (                        fellowship                        .                        contains                        (                        gandalf                        ));                        }                        @Test                        void                        ensureThatOneRingBearerIsPartOfTheFellowship                        ()                        {                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        Map                        <                        Ring                        ,                        TolkienCharacter                        >                        ringBearers                        =                        dataService                        .                        getRingBearers                        ();                        assertTrue                        (                        ringBearers                        .                        values                        ().                        stream                        ().                        anyMatch                        (                        ringBearer                        ->                        fellowship                        .                        contains                        (                        ringBearer                        )));                        }                        @RepeatedTest                        (                        1000                        )                        @Tag                        (                        "slow"                        )                        @DisplayName                        (                        "Ensure that we can call getFellowShip multiple times"                        )                        void                        ensureThatWeCanRetrieveFellowshipMultipleTimes                        ()                        {                        dataService                        =                        new                        DataService                        ();                        assertNotNull                        (                        dataService                        .                        getFellowship                        ());                        }                        @Test                        void                        ensureOrdering                        ()                        {                        // ensure that the order of the fellowship is:                        // frodo, sam, merry,pippin, gandalf,legolas,gimli,aragorn,boromir                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Frodo"                        ),                        fellowship                        .                        get                        (                        0                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Sam"                        ),                        fellowship                        .                        get                        (                        1                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Merry"                        ),                        fellowship                        .                        get                        (                        2                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Pippin"                        ),                        fellowship                        .                        get                        (                        3                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Gandalf"                        ),                        fellowship                        .                        get                        (                        4                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Legolas"                        ),                        fellowship                        .                        get                        (                        5                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Gimli"                        ),                        fellowship                        .                        get                        (                        6                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Aragorn"                        ),                        fellowship                        .                        get                        (                        7                        ));                        assertEquals                        (                        dataService                        .                        getFellowshipCharacter                        (                        "Boromir"                        ),                        fellowship                        .                        get                        (                        8                        ));                        }                        @Test                        void                        ensureAge                        ()                        {                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        // test to ensure that all hobbits and men are younger than 100 years                        // also ensure that the elfs, dwars the maia are all older than 100 years                        assertTrue                        (                        fellowship                        .                        stream                        ()                        .                        filter                        (                        fellow                        ->                        fellow                        .                        getRace                        ().                        equals                        (                        HOBBIT                        )                        ||                        fellow                        .                        getRace                        ().                        equals                        (                        Race                        .                        MAN                        ))                        .                        allMatch                        (                        fellow                        ->                        fellow                        .                        age                        <                        100                        ));                        assertTrue                        (                        fellowship                        .                        stream                        ().                        filter                        (                        fellow                        ->                        fellow                        .                        getRace                        ().                        equals                        (                        Race                        .                        ELF                        )                        ||                        fellow                        .                        getRace                        ().                        equals                        (                        Race                        .                        DWARF                        )                        ||                        fellow                        .                        getRace                        ().                        equals                        (                        Race                        .                        MAIA                        ))                        .                        allMatch                        (                        fellow                        ->                        fellow                        .                        age                        >                        100                        ));                        }                        @Test                        void                        ensureThatFellowsStayASmallGroup                        ()                        {                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        assertThrows                        (                        IndexOutOfBoundsException                        .                        class                        ,                        ()                        ->                        fellowship                        .                        get                        (                        20                        ));                        }                        }                                          

You actually found errors in the DataService implementations, adjust the following method:

                                              public                        TolkienCharacter                        getFellowshipCharacter                        (                        String                        name                        )                        {                        List                        <                        TolkienCharacter                        >                        list                        =                        getFellowship                        ();                        return                        list                        .                        stream                        ().                        filter                        (                        s                        ->                        s                        .                        getName                        ().                        equals                        (                        name                        )).                        findFirst                        ().                        orElseGet                        (()                        ->                        null                        );                        }                                          

7.4. Verify on command line

Verify that your code compiles and your test are running via the command line with:

  • mvn clean verify in case you are using Maven

  • ./gradlew test in case you are using Gradle

7.5. Add a long running method to your data service

Add a fake update method to your DataService which takes a long time to update the data and returns true on success.

                                      public                    boolean                    update                    ()                    {                    try                    {                    Thread                    .                    sleep                    (                    2000                    );                    }                    catch                    (                    InterruptedException                    e                    )                    {                    e                    .                    printStackTrace                    ();                    }                    return                    true                    ;                    }                                  

7.6. Develop a test to constrain the execution time of the long running method

Create a new test method in your DataServiceTest. Use the assertTimeout assert statement to ensure that this test does not run longer than 3 seconds.

Solution
                                          @Test                      public                      void                      ensureServiceDoesNotRunToLong                      ()                      {                      assertTimeout                      (                      Duration                      .                      ofSeconds                      (                      3                      ),()->                      dataService                      .                      update                      ());                      }                                      

8. Exercise: Develop unit tests for a regular expression utility method for email verification

8.1. Create the data model used for testing

Create the com.vogella.unittest.email package and copy and paste the following classes on it.

                                      package                    com.vogella.unittest.email                    ;                    import                    java.util.regex.Pattern                    ;                    public                    class                    EmailValidator                    {                    /**      * Email validation pattern.      */                    public                    static                    final                    Pattern                    EMAIL_PATTERN                    =                    Pattern                    .                    compile                    (                    "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}"                    +                    "\\@"                    +                    "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}"                    +                    "("                    +                    "\\."                    +                    "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}"                    +                    ")+"                    );                    private                    boolean                    mIsValid                    =                    false                    ;                    public                    boolean                    isValid                    ()                    {                    return                    mIsValid                    ;                    }                    /**      * Validates if the given input is a valid email address.      *      * @param emailPattern The {@link Pattern} used to validate the given email.      * @param email        The email to validate.      * @return {@code true} if the input is a valid email. {@code false} otherwise.      */                    public                    static                    boolean                    isValidEmail                    (                    CharSequence                    email                    )                    {                    return                    email                    !=                    null                    &&                    EMAIL_PATTERN                    .                    matcher                    (                    email                    ).                    matches                    ();                    }                    }                                  

8.2. Write tests for the model and the services

Create the following test class.

                                      package                    com.vogella.unittest.email                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertFalse                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertTrue                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    fail                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    EmailValidatorTest                    {                    // TODO Write test for EmailValidator                    // The names of the methods should give you a pointer what to test for                    @Test                    public                    void                    ensureThatEmailValidatorReturnsTrueForValidEmail                    ()                    {                    assertTrue                    (                    EmailValidator                    .                    isValidEmail                    (                    "lars.vogel@gmail.com"                    ));                    }                    @Test                    @DisplayName                    (                    "Ensure that the usage of a subdomain is still valid, see https://en.wikipedia.org/wiki/Subdomain"                    )                    public                    void                    emailValidator_CorrectEmailSubDomain_ReturnsTrue                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    @Test                    @DisplayName                    (                    "Ensure that a missiong top level domain returns false"                    )                    public                    void                    emailValidator_InvalidEmailNoTld_ReturnsFalse                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    @Test                    public                    void                    emailValidator_InvalidEmailDoubleDot_ReturnsFalse                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    @Test                    public                    void                    emailValidator_InvalidEmailNoUsername_ReturnsFalse                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    @Test                    public                    void                    emailValidator_EmptyString_ReturnsFalse                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    @Test                    public                    void                    emailValidator_NullEmail_ReturnsFalse                    ()                    {                    fail                    (                    "Fixme"                    );                    }                    }                                  

Fix all the failing test, unfortunately the test specification is not very good. Try to write reasonable tests which fit the method name.

8.3. Verify

Run your new test via the IDE. Verify that your code compiles and your test are running via the command line.

8.4. Solution

The following listing contains a possible implementation of the test.

Solution
                                          package                      com.vogella.unittest.email                      ;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      Assertions                      .                      assertFalse                      ;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      Assertions                      .                      assertTrue                      ;                      import                      org.junit.jupiter.api.Test                      ;                      class                      EmailValidatorTest                      {                      @Test                      void                      ensureThatEmailValidatorReturnsTrueForValidEmail                      ()                      {                      assertTrue                      (                      EmailValidator                      .                      isValidEmail                      (                      "lars.vogel@gmail.com"                      ));                      }                      @Test                      void                      emailValidator_CorrectEmailSubDomain_ReturnsTrue                      ()                      {                      assertTrue                      (                      EmailValidator                      .                      isValidEmail                      (                      "lars.vogel@analytics.gmail.com"                      ));                      }                      @Test                      void                      emailValidator_InvalidEmailNoTld_ReturnsFalse                      ()                      {                      assertFalse                      (                      EmailValidator                      .                      isValidEmail                      (                      "lars.vogel@gmail"                      ));                      }                      @Test                      void                      emailValidator_InvalidEmailDoubleDot_ReturnsFalse                      ()                      {                      assertTrue                      (                      EmailValidator                      .                      isValidEmail                      (                      "lars..vogel@gmail.com"                      ));                      assertFalse                      (                      EmailValidator                      .                      isValidEmail                      (                      "lars..vogel@gmail..com"                      ));                      }                      @Test                      void                      emailValidator_InvalidEmailNoUsername_ReturnsFalse                      ()                      {                      assertFalse                      (                      EmailValidator                      .                      isValidEmail                      (                      "@gmail.com"                      ));                      }                      @Test                      void                      emailValidator_EmptyString_ReturnsFalse                      ()                      {                      assertFalse                      (                      EmailValidator                      .                      isValidEmail                      (                      ""                      ));                      }                      @Test                      void                      emailValidator_NullEmail_ReturnsFalse                      ()                      {                      assertFalse                      (                      EmailValidator                      .                      isValidEmail                      (                      null                      ));                      }                      }                                      

9. Exercise: Testing exceptions and conditional enablement

9.1. Write tests checking for exceptions

We also want to check that exceptions with the correct error messages are thrown, if we call the class under test with incorrect data.

Create the following test class.

                                      package                    com.vogella.unittest.services                    ;                    import                    static                    com                    .                    vogella                    .                    unittest                    .                    model                    .                    Race                    .                    HOBBIT                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertThrows                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    fail                    ;                    import                    org.junit.jupiter.api.Disabled                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.Test                    ;                    import                    com.vogella.unittest.model.TolkienCharacter                    ;                    public                    class                    DataModelAssertThrowsTest                    {                    @Test                    @DisplayName                    (                    "Ensure that access to the fellowship throws exception outside the valid range"                    )                    void                    exceptionTesting                    ()                    {                    DataService                    dataService                    =                    new                    DataService                    ();                    Throwable                    exception                    =                    assertThrows                    (                    IndexOutOfBoundsException                    .                    class                    ,                    ()                    ->                    dataService                    .                    getFellowship                    ().                    get                    (                    20                    ));                    assertEquals                    (                    "Index 20 out of bounds for length 9"                    ,                    exception                    .                    getMessage                    ());                    }                    @Test                    @Disabled                    (                    "Please fix and enable"                    )                    public                    void                    ensureThatAgeMustBeLargerThanZeroViaSetter                    ()                    {                    TolkienCharacter                    frodo                    =                    new                    TolkienCharacter                    (                    "Frodo"                    ,                    33                    ,                    HOBBIT                    );                    // use assertThrows() rule to check that the message is:                    // Age is not allowed to be smaller than zero                    frodo                    .                    setAge                    (-                    1                    );                    }                    @Test                    @Disabled                    (                    "Please fix and enable"                    )                    public                    void                    testThatAgeMustBeLargerThanZeroViaConstructor                    ()                    {                    // use assertThrows() rule to check that an IllegalArgumentException exception is thrown and                    // that the message is:                    // "Age is not allowed to be smaller than zero"                    TolkienCharacter                    frodo                    =                    new                    TolkienCharacter                    (                    "Frodo"                    ,                    -                    1                    ,                    HOBBIT                    );                    }                    }                                  

Fix the disabled tests and enable them. The name should give a good indication what you have to do test here.

You may discover that the data model does not behave a expected by the test, fix them in this case.

9.2. Verify

Run your update test via the IDE. Verify that your code compiles and your test are running via the command line with the mvn clean verify.

9.3. Solution

Solution
                                              package                        com.vogella.unittest.services                        ;                        import                        static                        com                        .                        vogella                        .                        unittest                        .                        model                        .                        Race                        .                        HOBBIT                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertEquals                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertThrows                        ;                        import                        java.util.List                        ;                        import                        org.junit.jupiter.api.DisplayName                        ;                        import                        org.junit.jupiter.api.Test                        ;                        import                        com.vogella.unittest.model.TolkienCharacter                        ;                        class                        DataModelAssertThrowsTest                        {                        @Test                        @DisplayName                        (                        "Ensure that access to the fellowship throws exception outside the valid range"                        )                        void                        ensureThatIndexOutOfBoundMessageForFellowAccessIsCorrect                        ()                        {                        DataService                        dataService                        =                        new                        DataService                        ();                        List                        <                        TolkienCharacter                        >                        fellowship                        =                        dataService                        .                        getFellowship                        ();                        Throwable                        exception                        =                        assertThrows                        (                        IndexOutOfBoundsException                        .                        class                        ,                        ()                        ->                        fellowship                        .                        get                        (                        20                        ));                        assertEquals                        (                        "Index 20 out of bounds for length 9"                        ,                        exception                        .                        getMessage                        ());                        }                        @Test                        void                        ensureThatAgeMustBeLargerThanZeroViaSetter                        ()                        {                        // Age is not allowed to be smaller than zero                        TolkienCharacter                        frodo                        =                        new                        TolkienCharacter                        (                        "Frodo"                        ,                        33                        ,                        HOBBIT                        );                        assertThrows                        (                        IllegalArgumentException                        .                        class                        ,                        ()                        ->                        frodo                        .                        setAge                        (-                        1                        ));                        }                        @Test                        void                        ensureThatAgeMustBeLargerThanZeroViaConstructor                        ()                        {                        // Age is not allowed to be smaller than zero                        IllegalArgumentException                        exception                        =                        assertThrows                        (                        IllegalArgumentException                        .                        class                        ,                        ()                        ->                        new                        TolkienCharacter                        (                        "Frodo"                        ,                        -                        1                        ,                        HOBBIT                        ));                        assertEquals                        (                        "Age is not allowed to be smaller than zero"                        ,                        exception                        .                        getMessage                        ());                        }                        }                                          

The test indicates that you need to update the TolkienCharacter constructor.

                                              public                        TolkienCharacter                        (                        String                        name                        ,                        int                        age                        ,                        Race                        race                        )                        {                        this                        .                        name                        =                        name                        ;                        setAge                        (                        age                        );                        this                        .                        race                        =                        race                        ;                        }                                          

9.4. Enable test only on certain platforms

Write this test and adjust it so that is only runs on the operating system your are using.

                                      package                    com.vogella.unittest.platform                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertTrue                    ;                    import                    org.junit.jupiter.api.Assumptions                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    LinuxTests                    {                    @Test                    void                    testName                    ()                    throws                    Exception                    {                    // only run on Linux                    Assumptions                    .                    assumeTrue                    (                    System                    .                    getProperty                    (                    "os.name"                    ).                    contains                    (                    "Linux"                    ));                    assertTrue                    (                    true                    );                    }                    }                                  

10. Exercise: Writing nested tests to group tests for display

10.1. Write tests

Create the following test.

                                      package                    com.vogella.unittest.nested                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    java.util.Arrays                    ;                    import                    java.util.List                    ;                    import                    org.junit.jupiter.api.BeforeEach                    ;                    import                    org.junit.jupiter.api.DisplayName                    ;                    import                    org.junit.jupiter.api.Nested                    ;                    import                    org.junit.jupiter.api.Test                    ;                    class                    UsingNestedTests                    {                    private                    List                    <                    String                    >                    list                    ;                    @BeforeEach                    void                    setup                    ()                    {                    list                    =                    Arrays                    .                    asList                    (                    "JUnit 5"                    ,                    "Mockito"                    );                    }                    @Test                    void                    listTests                    ()                    {                    assertEquals                    (                    2                    ,                    list                    .                    size                    ());                    }                    // TODO define inner class with @Nestled                    // write one tests named checkFirstElement() to check that the first list element is "JUnit 4"                    // write one tests named checkSecondElement() to check that the first list element is "JUnit 4"                    @DisplayName                    (                    "Grouped tests for checking members"                    )                    @Nested                    class                    CheckMembers                    {                    @Test                    void                    checkFirstElement                    ()                    {                    assertEquals                    ((                    "JUnit 5"                    ),                    list                    .                    get                    (                    0                    ));                    }                    @Test                    void                    checkSecondElement                    ()                    {                    assertEquals                    ((                    "Mockito"                    ),                    list                    .                    get                    (                    1                    ));                    }                    }                    }                                  

10.2. Solution

The following listing contains a possible implementation of the test.

Solution
                                          package                      com.vogella.unittest.nested                      ;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      Assertions                      .                      assertEquals                      ;                      import                      java.util.Arrays                      ;                      import                      java.util.List                      ;                      import                      org.junit.jupiter.api.BeforeEach                      ;                      import                      org.junit.jupiter.api.DisplayName                      ;                      import                      org.junit.jupiter.api.Nested                      ;                      import                      org.junit.jupiter.api.Test                      ;                      class                      UsingNestedTests                      {                      private                      List                      <                      String                      >                      list                      ;                      @BeforeEach                      void                      setup                      ()                      {                      list                      =                      Arrays                      .                      asList                      (                      "JUnit 5"                      ,                      "Mockito"                      );                      }                      @Test                      void                      listTests                      ()                      {                      assertEquals                      (                      2                      ,                      list                      .                      size                      ());                      }                      }                                      

10.3. Run tests

Run the test from your IDE and review how the grouped tests are displayed.

11. Exercise: Testing multiple parameter

11.1. Create class for testing

Create the com.vogella.unittest.converter package and copy and paste the following class on it.

                                      package                    com.vogella.unittest.converter                    ;                    public                    class                    ConverterUtil                    {                    // converts to celsius                    public                    static                    float                    convertFahrenheitToCelsius                    (                    float                    fahrenheit                    )                    {                    return                    ((                    fahrenheit                    -                    32                    )                    *                    5                    /                    9                    );                    }                    // converts to fahrenheit                    public                    static                    float                    convertCelsiusToFahrenheit                    (                    float                    celsius                    )                    {                    return                    ((                    celsius                    *                    9                    )                    /                    5                    )                    +                    32                    ;                    }                    }                                  

11.2. Write a dynamic test

Create the following test class.

                                      package                    com.vogella.unittest.converter                    ;                    import                    java.util.Arrays                    ;                    import                    java.util.stream.Stream                    ;                    import                    org.junit.jupiter.api.DynamicTest                    ;                    import                    org.junit.jupiter.api.TestFactory                    ;                    class                    ConverterUtilTest                    {                    int                    [][]                    celsiusFahrenheitMapping                    =                    new                    int                    [][]                    {                    {                    10                    ,                    50                    },                    {                    40                    ,                    104                    },                    {                    0                    ,                    32                    }                    };                    @TestFactory                    Stream                    <                    DynamicTest                    >                    ensureThatCelsiumConvertsToFahrenheit                    ()                    {                    return                    Arrays                    .                    stream                    (                    celsiusFahrenheitMapping                    ).                    map                    (                    entry                    ->                    {                    // access celcius and fahrenheit from entry                    int                    celsius                    =                    entry                    [                    0                    ];                    int                    fahrenheit                    =                    entry                    [                    1                    ];                    return                    null                    ;                    // return a dynamicTest which checks that that the convertion from celcius to                    // fahrenheit is correct                    });                    }                    Stream                    <                    DynamicTest                    >                    ensureThatFahrenheitToCelsiumConverts                    ()                    {                    return                    null                    ;                    // TODO Write a similar test fahrenheit to celsius                    }                    }                                  

Fix all the failing test, unfortunately the test specification is not very good. Try to write reasonable tests which fit the method name.

Show Solution
                                          package                      com.vogella.unittest.converter                      ;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      Assertions                      .*;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      DynamicTest                      .                      dynamicTest                      ;                      import                      java.util.Arrays                      ;                      import                      java.util.stream.Stream                      ;                      import                      org.junit.jupiter.api.AfterEach                      ;                      import                      org.junit.jupiter.api.BeforeEach                      ;                      import                      org.junit.jupiter.api.DynamicTest                      ;                      import                      org.junit.jupiter.api.Test                      ;                      import                      org.junit.jupiter.api.TestFactory                      ;                      class                      ConverterUtilTest                      {                      @TestFactory                      public                      Stream                      <                      DynamicTest                      >                      ensureThatCelsiumConvertsToFahrenheit                      ()                      {                      ConverterUtil                      converter                      =                      new                      ConverterUtil                      ();                      int                      [][]                      data                      =                      new                      int                      [][]                      {                      {                      10                      ,                      50                      },                      {                      40                      ,                      104                      },                      {                      0                      ,                      32                      }                      };                      return                      Arrays                      .                      stream                      (                      data                      ).                      map                      (                      entry                      ->                      {                      int                      celsius                      =                      entry                      [                      0                      ];                      int                      fahrenheit                      =                      entry                      [                      1                      ];                      return                      dynamicTest                      (                      celsius                      +                      " Celsius are "                      +                      fahrenheit                      ,                      ()                      ->                      {                      assertEquals                      (                      fahrenheit                      ,                      converter                      .                      convertCelsiusToFahrenheit                      (                      celsius                      ));                      });                      });                      }                      @TestFactory                      public                      Stream                      <                      DynamicTest                      >                      ensureThatFahrenheitConvertsToCelsius                      ()                      {                      ConverterUtil                      converter                      =                      new                      ConverterUtil                      ();                      int                      [][]                      data                      =                      new                      int                      [][]                      {                      {                      10                      ,                      50                      },                      {                      40                      ,                      104                      },                      {                      0                      ,                      32                      }                      };                      return                      Arrays                      .                      stream                      (                      data                      ).                      map                      (                      entry                      ->                      {                      int                      celsius                      =                      entry                      [                      0                      ];                      int                      fahrenheit                      =                      entry                      [                      1                      ];                      return                      dynamicTest                      (                      celsius                      +                      " Celsius are "                      +                      fahrenheit                      ,                      ()                      ->                      {                      assertEquals                      (                      celsius                      ,                      converter                      .                      convertFahrenheitToCelsius                      (                      fahrenheit                      ));                      });                      });                      }                      }                                      

11.3. Verify

Run your new test via the IDE and ensure that you have 6 tests running succesfull.y

Verify that your code compiles and your test are running via the command line either with ./gradlew test`or with the `mvn clean verify depending on your build system.

12. Exercise: Testing with multiple input parameter

Dynamic tests are included in the regular JUnit 5 library, which you already included. To use parameters in your tests, you have to add the junit-jupiter-params library.

12.1. Add dependency

If you are using Maven add the following dependency to junit-jupiter-params to your Maven pom file.

                                                            org.junit.jupiter                      junit-jupiter-params                      5.7.2                      test                                                      

If you are using Gradle add the following to your build.gradle file

                  implementation 'org.junit.jupiter:junit-jupiter-params:5.7.2'                

12.2. Write a parameterized test

Review the following code:

                                      package                    com.vogella.unittest.converter                    ;                    import                    static                    org                    .                    junit                    .                    jupiter                    .                    api                    .                    Assertions                    .                    assertEquals                    ;                    import                    org.junit.jupiter.params.ParameterizedTest                    ;                    import                    org.junit.jupiter.params.provider.MethodSource                    ;                    class                    ParameterizedExampleTest                    {                    static                    int                    [][]                    data                    ()                    {                    return                    new                    int                    [][]                    {                    {                    1                    ,                    2                    ,                    2                    },                    {                    5                    ,                    3                    ,                    15                    },                    {                    121                    ,                    4                    ,                    484                    }                    };                    }                    @ParameterizedTest                    (                    name                    =                    "{index} called with: {0}"                    )                    @MethodSource                    (                    value                    =                    "data"                    )                    void                    testWithStringParameter                    (                    int                    []                    data                    )                    {                    MyClass                    tester                    =                    new                    MyClass                    ();                    int                    m1                    =                    data                    [                    0                    ];                    int                    m2                    =                    data                    [                    1                    ];                    int                    expected                    =                    data                    [                    2                    ];                    assertEquals                    (                    expected                    ,                    tester                    .                    multiply                    (                    m1                    ,                    m2                    ));                    }                    // class to be tested                    class                    MyClass                    {                    public                    int                    multiply                    (                    int                    i                    ,                    int                    j                    )                    {                    return                    i                    *                    j                    ;                    }                    }                    }                                  

Create a new test method in ConverterUtilTest which also uses a parameterized test.

12.3. Verify

Run your new test via the IDE.

convertertestresult10

Verify that your code compiles and your test are running via the command line with the ./gradlew test or mvn clean verify command based on your build system.

12.4. Add more options

ParameterizedTest are very flexible in sense of their input. The following lists a few more. Add these to your test and run the tests again.

                                      @ParameterizedTest                    @ValueSource                    (                    strings                    =                    {                    "WINDOW"                    ,                    "Microsoft Windows [Version 10.?]"                    })                    void                    ensureWindowsStringContainWindow                    (                    String                    name                    )                    {                    assertTrue                    (                    name                    .                    toLowerCase                    ().                    contains                    (                    "window"                    ));                    }                    @DisplayName                    (                    "A negative value for year is not supported by the leap year computation."                    )                    @ParameterizedTest                    (                    name                    =                    "For example, year {0} is not supported."                    )                    @ValueSource                    (                    ints                    =                    {                    -                    1                    ,                    -                    4                    })                    void                    ensureYear                    (                    int                    year                    )                    {                    assertTrue                    (                    year                    <                    0                    );                    }                    @ParameterizedTest                    (                    name                    =                    "{0} * {1} = {2}"                    )                    @CsvSource                    ({                    "0,    1,   0"                    ,                    "1,    2,   2"                    ,                    "49,  50, 2450"                    ,                    "1,  100, 100"                    })                    void                    add                    (                    int                    first                    ,                    int                    second                    ,                    int                    expectedResult                    )                    {                    MyClass                    calculator                    =                    new                    MyClass                    ();                    assertEquals                    (                    expectedResult                    ,                    calculator                    .                    multiply                    (                    first                    ,                    second                    ),                    ()                    ->                    first                    +                    " * "                    +                    second                    +                    " should equal "                    +                    expectedResult                    );                    }                                  

13. Exercise: Using the @TempDir annotation to create temporary files and paths

In this exercise you learn how to use the @TempDir annotation to let JUnit 5 create files and paths on request in your test and to automatically remove them after the test.

Java 11 API for creating files:

13.1. Create class under test

Create the following class

                                      package                    com.vogella.unittest.file                    ;                    import                    java.io.IOException                    ;                    import                    java.nio.charset.StandardCharsets                    ;                    import                    java.nio.file.Files                    ;                    import                    java.nio.file.Path                    ;                    import                    java.nio.file.StandardOpenOption                    ;                    public                    class                    FileWriter                    {                    private                    FileWriter                    ()                    {                    }                    public                    static                    void                    createFile                    (                    Path                    path                    )                    {                    try                    {                    Files                    .                    write                    (                    path                    ,                    ""                    .                    getBytes                    (                    StandardCharsets                    .                    UTF_8                    ),                    StandardOpenOption                    .                    CREATE                    ,                    StandardOpenOption                    .                    TRUNCATE_EXISTING                    );                    }                    catch                    (                    IOException                    e                    )                    {                    e                    .                    printStackTrace                    ();                    }                    }                    public                    static                    void                    appendFile                    (                    Path                    path                    ,                    String                    content                    )                    throws                    IOException                    {                    // image more logic here...                    Files                    .                    writeString                    (                    path                    ,                    content                    ,                    StandardOpenOption                    .                    APPEND                    );                    }                    }                                  

13.2. Write tests

Using the @TempDir annotation, create unit which test named FileWriterTest for the following:

  • Ensure that the Path given to you by the @TempDir annotation if writable

  • Ensure that a appending to a file with FileWriter.appendFile which has not yet been created with FileWriter.createFile throws an exception

  • Ensure that you can write to the file once you created it

HINT:

                                      @Test                    void                    ensureThatPathFromTempDirISWritable                    (                    @TempDir                    Path                    path                    )                    {                    // Check if the path created by the TempDir extension is writable                    // Check `Files` API for this                    }                                  

13.2.1. Solution

Solution
                                              package                        com.vogella.unittest.file                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertThrows                        ;                        import                        static                        org                        .                        junit                        .                        jupiter                        .                        api                        .                        Assertions                        .                        assertTrue                        ;                        import                        java.io.IOException                        ;                        import                        java.nio.file.Files                        ;                        import                        java.nio.file.Path                        ;                        import                        org.junit.jupiter.api.Test                        ;                        import                        org.junit.jupiter.api.io.TempDir                        ;                        class                        FileWriterTest                        {                        @Test                        void                        ensureThatPathFromTempDirISWritable                        (                        @TempDir                        Path                        path                        )                        {                        // Check if the path created by the TempDir extension is writable                        assertTrue                        (                        Files                        .                        isWritable                        (                        path                        ));                        }                        @Test                        void                        ensureThatNonExistingFileThrowsAnException                        (                        @TempDir                        Path                        path                        )                        {                        Path                        file                        =                        path                        .                        resolve                        (                        "content.txt"                        );                        assertThrows                        (                        IOException                        .                        class                        ,                        ()                        ->                        {                        FileWriter                        .                        appendFile                        (                        file                        ,                        "Hello"                        );                        });                        }                        @Test                        void                        ensureAppendingWorks                        (                        @TempDir                        Path                        path                        )                        throws                        IOException                        {                        Path                        file                        =                        path                        .                        resolve                        (                        "content.txt"                        );                        FileWriter                        .                        createFile                        (                        file                        );                        FileWriter                        .                        appendFile                        (                        file                        ,                        "Hello"                        );                        assertTrue                        (                        Files                        .                        isReadable                        (                        file                        ));                        // TODO check the content of the file                        }                        }                                          

14. Exercise: Testing for annotations

In this exercise you write test to check class under test for certain annotations.

14.1. Add dependency to @Inject

If you have not yet done this, add a dependency to javax.inject.

Maven:

                                      <dependency>                    <groupId>javax.inject</groupId>                    <artifactId>javax.inject</artifactId>                    <version>1</version>                    </dependency>                                  

Gradle:

                                      implementation                    'javax.inject:javax.inject:1'                                  

14.2. Create class under test

Create the following class

                                      package                    com.vogella.unittest.di                    ;                    import                    javax.inject.Inject                    ;                    public                    class                    Service                    {                    @Inject                    String                    s                    ;                    @Inject                    public                    Service                    ()                    {                    }                    @Inject                    public                    Service                    (                    String                    s                    )                    {                    this                    .                    s                    =                    s                    ;                    }                    }                                  

t validates that the Servic === Write tests

Write a test that validates that the Service class only has one constructor annotated with @Inject.

HINT:

  • The class has a `getConstructors method.

  • The Constructor has a method getAnnotation

14.3. Solution

Solution
                                          package                      com.vogella.unittest.di                      ;                      import                      static                      org                      .                      junit                      .                      jupiter                      .                      api                      .                      Assertions                      .                      assertEquals                      ;                      import                      java.lang.reflect.Constructor                      ;                      import                      javax.inject.Inject                      ;                      import                      org.junit.jupiter.api.Test                      ;                      class                      ServiceTest                      {                      @Test                      void                      ensureJSR330Constructor                      ()                      {                      int                      count                      =                      0                      ;                      Constructor                      <?>[]                      constructors                      =                      Service                      .                      class                      .                      getConstructors                      ();                      for                      (                      Constructor                      <?>                      constructor                      :                      constructors                      )                      {                      Inject                      annotation                      =                      constructor                      .                      getAnnotation                      (                      Inject                      .                      class                      );                      if                      (                      annotation                      !=                      null                      )                      {                      count                      ++;                      }                      }                      assertEquals                      (                      1                      ,                      count                      );                      }                      }                                      

15. Exercise: Create test reports

Both Maven and Gradle allow to generate HTML report for unit tests.

Gradle creates these automatically, if you run the ./gradlew build command and with Maven you run the mvn clean verify surefire-report:report command.

Run this for your project and check the build folder for the generated test reports.

16. Exercise: Clone the JUnit5 Github repo and review tests

Import the project into your favorite IDE and review some of the tests, e.g. the platform-tests contains a lot of useful tests.

17. Overview of JUnit5 annotations

The following table gives an overview of the most important annotations in JUnit 5 from the org.junit.jupiter.api package.

Table 2. Annotations
Annotation Description

@Test

Identifies a method as a test method.

@Disabled("reason")

Disables a test method with an option reason.

@BeforeEach

Executed before each test. Used to prepare the test environment, e.g., initialize the fields in the test class, configure the environment, etc.

@AfterEach

Executed after each test. Used to cleanup the test environment, e.g., delete temporary data, restore defaults, cleanup expensive memory structures.

@DisplayName("<Name>")

<Name> that will be displayed by the test runner. In contrast to method names the name can contain spaces to improve readability.

@RepeatedTest(<Number>)

Similar to @Test but repeats the test a <Number> of times

@BeforeAll

Annotates a static method which is executed once, before the start of all tests. It is used to perform time intensive activities, for example, to connect to a database. Methods marked with this annotation need to be defined as static to work with JUnit.

@AfterAll

Annotates a static method which is executed once, after all tests have been finished. It is used to perform clean-up activities, for example, to disconnect from a database. Methods annotated with this annotation need to be defined as static to work with JUnit.

@TestFactory

Annotates a method which is a Factory for creating dynamic tests

@Nested

Lets you nest inner test classes to group your tests and to have additional @BeforeEach and @AfterEach methods.

@Tag("<TagName>")

Tags a test method, tests in JUnit 5 can be filtered by tag. E.g., run only tests tagged with "fast".

@ExtendWith

Lets you register an Extension class that adds functionality to the tests

18. Conclusion

JUnit 5 makes is easy to write software tests.

The implementation of all these examples and code snippets can be found over on Github. The Maven examples are located in JUnit with Maven and the Gradle examples are located in JUnit 5 with Gradle.