Junit 5 with Spring boot 2

Learn to write unit tests in Junit 5 in Spring boot 2 applications with help of RestTemplate, to test the REST APIs or spring mvc applications.

1. Maven dependencies

By default, spring-boot-starter-test dependency imports the junit 4 dependencies into Spring boot application. To use Junit 5, we must exclude Junit 4 and include Junit 5 into project dependencies.

We are using latest spring boot version (to date) i.e. 2.1.7.RELEASE.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.howtodoinjava.demo</groupId>
	<artifactId>springbootdemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>SpringBootDemo</name>
	<description>Spring Boot2 REST API Demo for http://howtodoinjava.com</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.7.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>

			<!-- exclude junit 4 -->
			<exclusions>
				<exclusion>
					<groupId>junit</groupId>
					<artifactId>junit</artifactId>
				</exclusion>
			</exclusions>

		</dependency>

		<!-- junit 5 -->
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-api</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2. Write Junit 5 tests

If this is new application then we shall be writing new unit tests otherwise we shall be making code changes to migrate from Junit 4 to Junit 5.

2.1. Remove @RunWith(SpringRunner.class)

With Junit 5, we do not need @RunWith(SpringRunner.class) anymore. Spring tests are executed with @ExtendWith(SpringExtension.class) and @SpringBootTest and the other @…Test annotations are already annotated with it.

2.2. Use Junit 5 Assertions

In stead of org.junit.Assert to assert, we will use org.junit.jupiter.api.Assertions class for validating the expected output with actual output of a testcase. All JUnit Jupiter assertions are static methods.

Read More: JUnit 5 Assertions Examples

2.3. Maven surefire plugin

Use maven’s surefire plugin to include or exlcude tests based on tags, or configure the test runtime. [Link]

package com.howtodoinjava.rest;

import java.net.URI;
import java.net.URISyntaxException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import com.howtodoinjava.rest.model.Employee;

//@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class SpringBootDemoApplicationTests 
{   
    @LocalServerPort
    int randomServerPort;
    
    @Test
    public void testAddEmployeeSuccess() throws URISyntaxException 
    {
        RestTemplate restTemplate = new RestTemplate();
        final String baseUrl = "http://localhost:"+randomServerPort+"/employees/";
        URI uri = new URI(baseUrl);
        Employee employee = new Employee(null, "Adam", "Gilly", "test@email.com");
        
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-COM-PERSIST", "true");      

        HttpEntity<Employee> request = new HttpEntity<>(employee, headers);
        
        ResponseEntity<String> result = restTemplate.postForEntity(uri, request, String.class);
        
        //Verify request succeed
        Assertions.assertEquals(201, result.getStatusCodeValue());
    }
    
    @Test
    public void testAddEmployeeMissingHeader() throws URISyntaxException 
    {
        RestTemplate restTemplate = new RestTemplate();
        final String baseUrl = "http://localhost:"+randomServerPort+"/employees/";
        URI uri = new URI(baseUrl);
        Employee employee = new Employee(null, "Adam", "Gilly", "test@email.com");
        
        HttpHeaders headers = new HttpHeaders();

        HttpEntity<Employee> request = new HttpEntity<>(employee, headers);
        
        try 
        {
            restTemplate.postForEntity(uri, request, String.class);
            Assertions.fail();
        }
        catch(HttpClientErrorException ex) 
        {
            //Verify bad request and missing header
        	Assertions.assertEquals(400, ex.getRawStatusCode());
        	Assertions.assertEquals(true, ex.getResponseBodyAsString().contains("Missing request header"));
        }
    }

    @Test
    public void testGetEmployeeListSuccessWithHeaders() throws URISyntaxException 
    {
        RestTemplate restTemplate = new RestTemplate();
        
        final String baseUrl = "http://localhost:"+randomServerPort+"/employees/";
        URI uri = new URI(baseUrl);
        
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-COM-LOCATION", "USA");

        HttpEntity<Employee> requestEntity = new HttpEntity<>(null, headers);

        try 
        {
            restTemplate.exchange(uri, HttpMethod.GET, requestEntity, String.class);
            Assertions.fail();
        }
        catch(HttpClientErrorException ex) 
        {
            //Verify bad request and missing header
        	Assertions.assertEquals(400, ex.getRawStatusCode());
        	Assertions.assertEquals(true, ex.getResponseBodyAsString().contains("Missing request header"));
        }
    }
}

Drop me your questions related to using junit 5 in spring boot 2 applications.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

1 thought on “Junit 5 with Spring boot 2”

Comments are closed.

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.