Junit Testing Spring REST Services

Introduction

In this tutorial we will see how to write Junit test cases on Spring REST services. Before continue to reading this tutorial please read first Spring RESTful Webservice CRUD Example

We have total four operations on this REST example. If you want you may add more operation such as find all products and apply Junit on it.

Prerequisites

Knowledge of Java, Junit, Spring

Spring RESTful Webservice CRUD Example

Example with Source Code

Here we will create the Junit test cases for Spring REST services.

Adding Dependencies

We need to add the required dependencies in order to write Junit test cases for Spring REST services.

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<!-- <scope>test</scope> -->
			<exclusions>
				<exclusion>
					<groupId>org.hamcrest</groupId>
					<artifactId>hamcrest-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.3.8.RELEASE</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-all</artifactId>
			<version>1.3</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>2.7.19</version>
			<exclusions>
				<exclusion>
					<groupId>org.hamcrest</groupId>
					<artifactId>hamcrest-core</artifactId>
				</exclusion>
			</exclusions>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.jayway.jsonpath</groupId>
			<artifactId>json-path</artifactId>
			<version>2.2.0</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

Creating Junit Class

The complete Junit class is given below

package roytuts.rest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.fasterxml.jackson.databind.ObjectMapper;
import roytuts.model.Product;
import roytuts.sevice.ProductService;
@RunWith(MockitoJUnitRunner.class)
public class SpringRestControllerTest {
	@Mock
	private ProductService service;
	private MockMvc mockMvc;
	@Spy
	@InjectMocks
	private SpringRestController controller = new SpringRestController();
	@Before
	public void init() {
		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
	}
	@Test
	public void testGetProductById() throws Exception {
		Product product = new Product();
		product.setId(1);
		product.setName("Product name");
		product.setPrice(21540.00);
		Mockito.when(service.findProductById(Mockito.anyInt())).thenReturn(product);
		mockMvc.perform(MockMvcRequestBuilders.get("/product/1")).andExpect(MockMvcResultMatchers.status().is(200))
				.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1));
	}
	@Test
	public void testSaveProduct() throws Exception {
		Product product = new Product();
		product.setId(1);
		product.setName("Product name");
		product.setPrice(21540.00);
		ObjectMapper mapper = new ObjectMapper();
		String jsonString = mapper.writeValueAsString(product);
		Mockito.when(service.isProductAvailable(Mockito.any(Product.class))).thenReturn(false);
		Mockito.doNothing().when(service).saveProduct(Mockito.any(Product.class));
		MvcResult result = mockMvc
				.perform(MockMvcRequestBuilders.post("/product").content(jsonString)
						.contentType(MediaType.APPLICATION_JSON))
				.andExpect(MockMvcResultMatchers.status().is(201)).andReturn();
		Assert.assertEquals(201, result.getResponse().getStatus());
	}
	@Test
	public void testUpdateProduct() throws Exception {
		Product product = new Product();
		product.setId(1);
		product.setName("Product name");
		product.setPrice(21540.00);
		ObjectMapper mapper = new ObjectMapper();
		String jsonString = mapper.writeValueAsString(product);
		Mockito.when(service.findProductById(Mockito.anyInt())).thenReturn(product);
		Mockito.doNothing().when(service).updateProduct(Mockito.any(Product.class));
		mockMvc.perform(
				MockMvcRequestBuilders.put("/product").content(jsonString).contentType(MediaType.APPLICATION_JSON))
				.andExpect(MockMvcResultMatchers.status().is(200));
	}
	@Test
	public void testDeleteProductByid() throws Exception {
		Product product = new Product();
		product.setId(1);
		product.setName("Product name");
		product.setPrice(21540.00);
		Mockito.when(service.findProductById(Mockito.anyInt())).thenReturn(product);
		Mockito.doNothing().when(service).deleteProductById(Mockito.anyInt());
		mockMvc.perform(MockMvcRequestBuilders.delete("/product/1")).andExpect(MockMvcResultMatchers.status().is(200));
	}
}

We have used MockitoJunitRunner to run the Junit test cases. We have mocked the service class and we have used annotation @Spy and @InjectMocks on Controller class because we want to call the method of the real object and we want to inject the mocked objects into Controller respectively.

We have also used MockMvc object, which is a main entry point for server-side Spring MVC test support.

In test case method testGetProductById() we expect to return only one product from the controller method operation GET. So we have verified using the mockMvc.perform() and we don’t need any extra assertion for that.

In the test case method testSaveProduct() we expect the response status 201 and here we are returning result from mockMvc.perform() and after that we verifying the status. But if we would not have returned the result from the specified method we could have verified using the same way as we have verified for GET operation.

In test case method testUpdateProduct() we have tested the PUT operation and verified the status 200. Here we could have returned the result from mockMvc.perform() and verified using assertion but we verified at the same place while we are performing PUT operation using mockMvc.perform().

In test case method testDeleteProductByid() for DELETE operation we verified the status in the same way as PUT operation.

Testing Junit

When you run the above Junit test class you will see all tests are passed:

junit test for spring rest web services

Source Code

download source code

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *