Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 4536

The Basics of JUnit 5 – A Preview

$
0
0

I just released the Starter Class of "Learn Spring Security":

>> CHECK OUT THE COURSE

1. Overview

JUnit is one of the most popular unit testing frameworks for Java, so it is a big deal in the developer community when new major versions come out. An alpha version of JUnit 5 was released in early February, and it contains a number of exciting innovations.

This article will explore the new features of this release, and the main differences with previous versions.

2. Dependencies and Setup

Installing JUnit 5 is pretty straightforward. Just add the following dependency to your pom.xml:

<dependency>
    <groupId>org.junit</groupId>
    <artifactId>junit5-api</artifactId>
    <version>5.0.0-ALPHA</version>
</dependency>

However, at the moment no IDEs support JUnit 5 yet, so you will also have to specify a build script:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
    <dependencies>
        <dependency>
            <groupId>org.junit</groupId>
            <artifactId>surefire-junit5</artifactId>
            <version>5.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</plugin>

It is important to note that this version requires Java 8 to work.

When creating a test, make sure you import org.junit.gen5.api.Test, not org.junit.Test. Also, the test methods no longer need to be public; package local will do.

3. What’s New

JUnit 5 tries to take full advantage of the new features from Java 8, especially lambda expressions.

3.1. Assertions

Assertions have been moved to org.junit.gen5.api.Assertions and have been improved significantly. As mentioned earlier, you can now use lambdas in assertions:

@Test
void lambdaExpressions() {
    List<Integer> numbers = Arrays.asList(1, 2, 3);
    assertTrue(numbers
        .stream()
        .mapToInt(i -> i)
        .sum() > 5, () -> "Sum should be greater than 5");
}

Although the example above is trivial, one advantage of using the lambda expression for the assertion message is that it is lazily evaluated, which can save time and resources if the message construction is expensive.

It is also now possible to group assertions with assertAll() which will report any failed assertions within the group with a MultipleFailuresError:

 @Test
 void groupAssertions() {
     int[] numbers = {0, 1, 2, 3, 4};
     assertAll("numbers",
         () -> assertEquals(numbers[0], 1),
         () -> assertEquals(numbers[3], 3),
         () -> assertEquals(numbers[4], 1)
     );
 }

This means it is now safer to make more complex assertions, as you will be able to pinpoint the exact location of any failure.

3.2. Assumptions

Assumptions are used to run tests only if certain conditions are met. This is typically used for external conditions that are required for the test to run properly, but which are not directly related to whatever is being tested.

You can declare an assumption with assumeTrue(), assumeFalse(), and assumingThat(). 

@Test
void trueAssumption() {
    assumeTrue(5 > 1);
    assertEquals(5 + 2, 7);
}

@Test
void falseAssumption() {
    assumeFalse(5 < 1);
    assertEquals(5 + 2, 7);
}

@Test
void assumptionThat() {
    String someString = "Just a string";
    assumingThat(
        someString.equals("Just a string"),
        () -> assertEquals(2 + 2, 4)
    );
}

If an assumption fails, a TestAbortedException is thrown and the test is simply skipped.

Assumptions also understand lambda expressions.

3.3. Exceptions

JUnit 5 improves support for exceptions. An expectThrows() method has been added that verifies that an expression throws an expression of a given type:

@Test
void shouldThrowException() {
    Throwable exception = expectThrows(UnsupportedOperationException.class, () -> {
      throw new UnsupportedOperationException("Not supported");
    });
    assertEquals(exception.getMessage(), "Not supported");
}

As the example demonstrates, JUnit 5 offers more control over the thrown exceptions than JUnit 4 used to. The most obvious implication is that it is now possible to easily get any information we might need about the exception, as we did in our example by inspecting the exception message.

3.4. Nested Tests

Nested tests have been added to allow developers to express complex relationships between different groups of tests. The syntax is quite straightforward – all you have to do is annotate an inner class with @Nested.

The JUnit documentation offers an elaborate example, which illustrates one of the possible uses.

3.5. Disabling Tests

Tests can now be disable with the @Disabled annotation.

@Test
@Disabled
void disabledTest() {
    assertTrue(false);
}

This test will not be run. The @Disabled annotation can be applied to either a test case or a test method and is equivalent to @Ignore from JUnit 4.

3.6. Tagging

Tags are the replacement for Categories from JUnit 4. Tags can be applied with the @Tag annotation. These allow developers to group and filter tests.

@Tag("Test case")
public class TaggedTest {

    @Test
    @Tag("Method")
    void testMethod() {
        assertEquals(2+2, 4);
    }
}

4. Conclusion

The writeup was a quick overview of the changes that are coming with JUnit 5.

It is important to note that at the moment of writing only the Alpha build was available, so some things might still change before release.

The examples used in this article can be found in the linked GitHub project.

Get the early-bird price (20% Off) of my upcoming "Learn Spring Security" Course:

>> CHECK OUT THE COURSE


Viewing all articles
Browse latest Browse all 4536

Trending Articles