You are currently viewing Spring Boot REST API Integration Testing with JUnit 5

Spring Boot REST API Integration Testing with JUnit 5

Hey guys in this post, we will learn about writing JUnit integration test cases for Spring Boot REST API. In the previous posts, we discussed writing the JUnit test cases for the Repository layer, Service layer, and Controller layer for the Spring Boot application, in case you miss those posts, you can check them now.

Integration testing is nothing but end-to-end testing, we will write the test cases to test the real implementation with real databases like MySQL, PostgreSQL, etc.

Writing Spring Boot REST API Integration testing with JUnit 5 is one of the most common things that we do every day in our day-to-day development. Most developers struggle in writing these integration test cases so this is the article for the spring boot rest api integration test example, follow this post till the end.




Read More:

Watch the Video


Configure datasource


Let’s configure the datasource for the MySQL database open  application.properties and add the following content

spring.jpa.show-sql=true

spring.datasource.url=jdbc:mysql://localhost:3306/moviesdb
spring.datasource.username=root
spring.datasource.password=scbushan05

spring.jpa.hibernate.ddl-auto=update

Create JPA Entity


Let’s create an JPA entity Movie.java inside in.bushansirgur.springbootjunit.modeland add the following content

package in.bushansirgur.springbootjunit.model;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "tbl_movies")
public class Movie {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	private String name;
	
	private String genera;
	
	private LocalDate releaseDate;
}

Create JPA Repository


Let’s create an interface MovieRepository.java inside in.bushansirgur.springbootjunit.repositoryand add the following content

package in.bushansirgur.springbootjunit.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import in.bushansirgur.springbootjunit.model.Movie;

public interface MovieRepository extends JpaRepository<Movie, Long>{
	
	List<Movie> findByGenera(String genera);
}

Create a Service


Let’s create a class MovieService.java inside in.bushansirgur.springbootjunit.serviceand add the following content




package in.bushansirgur.springbootjunit.service;

import java.util.List;

import org.springframework.stereotype.Service;

import in.bushansirgur.springbootjunit.model.Movie;
import in.bushansirgur.springbootjunit.repository.MovieRepository;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class MovieService {
	
	private final MovieRepository movieRepository;
	
	public Movie save(Movie movie) {
		return movieRepository.save(movie);
	}
	
	public List<Movie> getAllMovies() {
		return movieRepository.findAll();
	}
	
	public Movie getMovieById(Long id) {
		return movieRepository.findById(id).orElseThrow(() -> new RuntimeException("Movie found for the id "+id));	
	}
	
	public Movie updateMovie(Movie movie, Long id) {
		Movie existingMovie = movieRepository.findById(id).get();
		existingMovie.setGenera(movie.getGenera());
		existingMovie.setName(movie.getName());
		existingMovie.setReleaseDate(movie.getReleaseDate());
		return movieRepository.save(existingMovie);
	}
	
	public void deleteMovie(Long id) {
		Movie existingMovie = movieRepository.findById(id).get();
		movieRepository.delete(existingMovie);
		
	}
}

Create a Controller


Let’s create a class MovieController.java inside in.bushansirgur.springbootjunit.controllerand add the following content

package in.bushansirgur.springbootjunit.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import in.bushansirgur.springbootjunit.model.Movie;
import in.bushansirgur.springbootjunit.service.MovieService;

@RestController
@RequestMapping("/movies")
public class MovieController {
	
	@Autowired
	private MovieService movieService;
	
	@PostMapping
	@ResponseStatus(HttpStatus.CREATED)
	public Movie create(@RequestBody Movie movie) {
		return movieService.save(movie);
	}
	
	@GetMapping
	@ResponseStatus(HttpStatus.OK)
	public List<Movie> read() {
		return movieService.getAllMovies();
	}
	
	@GetMapping("/{id}")
	@ResponseStatus(HttpStatus.OK)
	public Movie read(@PathVariable Long id) {
		return movieService.getMovieById(id);
	}
	
	@DeleteMapping("/{id}")
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void delete(@PathVariable Long id) {
		movieService.deleteMovie(id);
	}
	
	@ResponseStatus(HttpStatus.OK)
	@PutMapping("/{id}")
	public Movie update(@PathVariable Long id, @RequestBody Movie movie) {
		return movieService.updateMovie(movie, id);
	}
}

Now we need to write integration test cases to test these REST APIs

Create JUnit class


In order to write the integration test cases create a JUnit class MoviesIntegrationTest.java inside src/test/java and add the following content

package in.bushansirgur.springbootjunit.integration;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.time.LocalDate;
import java.time.Month;
import java.util.List;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.web.client.RestTemplate;

import in.bushansirgur.springbootjunit.model.Movie;
import in.bushansirgur.springbootjunit.repository.MovieRepository;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MoviesIntegrartionTest {
	
	@LocalServerPort
	private int port;
	
	private String baseUrl = "http://localhost";
	
	private static RestTemplate restTemplate;

	private Movie avatarMovie;
	private Movie titanicMovie;
	
	@Autowired
	private MovieRepository movieRepository;
	
	@BeforeAll
	public static void init() {
		restTemplate = new RestTemplate();
	}
	
	@BeforeEach
	public void beforeSetup() {
		baseUrl = baseUrl + ":" +port + "/movies";
		
		avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 22));
		
		titanicMovie = new Movie();
		titanicMovie.setName("Titanic");
		titanicMovie.setGenera("Romance");
		titanicMovie.setReleaseDate(LocalDate.of(1999, Month.MAY, 20));
		
		avatarMovie = movieRepository.save(avatarMovie);
		titanicMovie = movieRepository.save(titanicMovie);
	}
	
	@AfterEach
	public void afterSetup() {
		movieRepository.deleteAll();
	}
	
	@Test
	void shouldCreateMovieTest() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 22));
		
		Movie newMovie = restTemplate.postForObject(baseUrl, avatarMovie, Movie.class);
		
		assertNotNull(newMovie);
		assertThat(newMovie.getId()).isNotNull();
	}
	
	@Test
	void shouldFetchMoviesTest() {
		
		
		List<Movie> list = restTemplate.getForObject(baseUrl, List.class);
		
		assertThat(list.size()).isEqualTo(2);
	}
	
	@Test
	void shouldFetchOneMovieTest() {
		
		Movie existingMovie = restTemplate.getForObject(baseUrl+"/"+avatarMovie.getId(), Movie.class);
		
		assertNotNull(existingMovie);
		assertEquals("Avatar", existingMovie.getName());
	}
	
	@Test
	void shouldDeleteMovieTest() {
		
		restTemplate.delete(baseUrl+"/"+avatarMovie.getId());
		
		int count = movieRepository.findAll().size();
		
		assertEquals(1, count);
	}
	
	@Test
	void shouldUpdateMovieTest() {
		
		avatarMovie.setGenera("Fantacy");
		
		restTemplate.put(baseUrl+"/{id}", avatarMovie, avatarMovie.getId());
		
		Movie existingMovie = restTemplate.getForObject(baseUrl+"/"+avatarMovie.getId(), Movie.class);
		
		assertNotNull(existingMovie);
		assertEquals("Fantacy", existingMovie.getGenera());
	}
}
  • @SpringBootTest: Spring Boot provides a convenient way to start up an application context to be used in a test. The @SpringBootTest annotation tells Spring Boot to look for the main configuration class (one with @SpringBootApplication, for instance) and use that to start a Spring application context.




  • (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT): With this configuration, Spring creates a WebApplicationContext for our integration test and starts the embedded servlet container on a random ephemeral port.
  • @LocalServerPort: It injects the HTTP port that got allocated at runtime. Provides a convenient alternative for @Value("${local.server.port}")

Now when we run the test class, we should see the green bar

Screenshot-2022-10-11-at-8-46-53-PM

That’s it for this article, in the next article. Thank you so much for reading this post, if you feel this post helped you then consider sharing this with your friends, colleagues, and social media.



Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

Leave a Reply