Spring Boot Rest 控制器单元测试
Spring Boot 提供了一种为 Rest Controller 文件编写单元测试的简单方法。 在 SpringJUnit4ClassRunner
和 MockMvc
的帮助下,我们可以创建一个 Web 应用程序上下文来为 Rest Controller 文件编写单元测试。
单元测试应该写在 src/test/java 目录下,用于编写测试的类路径资源应该放在 src/test/resources 目录下。
对于编写单元测试,我们需要在构建配置文件中添加 Spring Boot Starter Test 依赖项,如下所示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Gradle 用户可以在 build.gradle 文件中添加以下依赖项。
testCompile('org.springframework.boot:spring-boot-starter-test')
在编写测试用例之前,我们应该首先构建 RESTful Web 服务。 有关构建 RESTful Web 服务的更多信息,请参阅本教程中给出的相同章节。
为 REST 控制器编写单元测试
在本节中,让我们看看如何为 REST 控制器编写单元测试。
首先,我们需要使用 MockMvc
创建用于创建 Web 应用程序上下文的抽象类文件,并定义 mapToJson()
和 mapFromJson()
方法将 Java 对象转换为 JSON 字符串,并将 JSON 字符串转换为 Java 对象。
package com.jiyik.demo;
import java.io.IOException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
@WebAppConfiguration
public abstract class AbstractTest {
protected MockMvc mvc;
@Autowired
WebApplicationContext webApplicationContext;
protected void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
protected String mapToJson(Object obj) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
}
protected <T> T mapFromJson(String json, Class<T> clazz)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, clazz);
}
}
接下来,编写一个继承 AbstractTest
类的类文件,并为每个方法(如 GET、POST、PUT 和 DELETE)编写一个单元测试。
下面给出了 GET API 测试用例的代码。 此 API 用于查看产品列表。
@Test
public void getProductsList() throws Exception {
String uri = "/products";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri)
.accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
Product[] productlist = super.mapFromJson(content, Product[].class);
assertTrue(productlist.length > 0);
}
POST API 测试用例的代码如下。 此 API 用于创建产品。
@Test
public void createProduct() throws Exception {
String uri = "/products";
Product product = new Product();
product.setId("3");
product.setName("Ginger");
String inputJson = super.mapToJson(product);
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
.contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(201, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is created successfully");
}
PUT API 测试用例的代码如下。 此 API 用于更新现有商品。
@Test
public void updateProduct() throws Exception {
String uri = "/products/2";
Product product = new Product();
product.setName("Lemon");
String inputJson = super.mapToJson(product);
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put(uri)
.contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is updated successsfully");
}
删除 API 测试用例的代码如下。 此 API 将删除现有商品。
@Test
public void deleteProduct() throws Exception {
String uri = "/products/2";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete(uri)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is deleted successsfully");
}
完整的控制器测试类文件如下所示
package com.jiyik.demo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import com.tutorialspoint.demo.model.Product;
public class ProductServiceControllerTest extends AbstractTest {
@Override
@Before
public void setUp() {
super.setUp();
}
@Test
public void getProductsList() throws Exception {
String uri = "/products";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri)
.accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
Product[] productlist = super.mapFromJson(content, Product[].class);
assertTrue(productlist.length > 0);
}
@Test
public void createProduct() throws Exception {
String uri = "/products";
Product product = new Product();
product.setId("3");
product.setName("Ginger");
String inputJson = super.mapToJson(product);
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(inputJson)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(201, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is created successfully");
}
@Test
public void updateProduct() throws Exception {
String uri = "/products/2";
Product product = new Product();
product.setName("Lemon");
String inputJson = super.mapToJson(product);
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put(uri)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(inputJson)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is updated successsfully");
}
@Test
public void deleteProduct() throws Exception {
String uri = "/products/2";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete(uri)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
assertEquals(content, "Product is deleted successsfully");
}
}
现在,我们可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。
对于 Maven,使用下面给出的命令
$ mvn clean install
成功之后,我们可以在 target 目录下找到 JAR 文件。
对于 Gradle,使用下面给出的命令
$ gradle clean build