写完代码后,测试是必不可少的步骤,现在来介绍一下基于SpringBoot的测试方法。
基于SpringBoot框架写完相应功能的Controller之后,然后就可以测试功能是否正常,本博客列举MockMvc
和RestTemplate
两种方式来测试。
准备代码
实体类Person
public class Person {
private String id;
private String name;
public Person() {}
public Person(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
}
控制器PersonController
import javax.validation.Valid;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.test.springboottest.bean.Person;
@RestController
@RequestMapping("/person")
public class PersonController {
/**
* 使用对象方式传递数据
* @param person 保存对象
* @return
*/
@RequestMapping(value="/add",method=RequestMethod.POST)
public Person addUser(Person person){
person.setId(UUID.randomUUID().toString().substring(0, 6));
return person;
}
/**
* 使用JSON方式传递数据
* @param person 保存对象
* @return
*/
@RequestMapping(value="/addJson",method=RequestMethod.POST)
public Person addUserByJson(@RequestBody Person person){
person.setId(UUID.randomUUID().toString().substring(0, 6));
return person;
}
@RequestMapping(value="/get/{id}",method=RequestMethod.GET)
public Person getUser(@PathVariable String id){
Person person = new Person("Mepper");
person.setId(id);
return person;
}
}
上述代码即为简化版的数据的增查的功能。
MockMvc方式
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.springboottest.bean.Person;
@SpringBootTest//系统会自动加载Spring Boot容器
@RunWith(SpringRunner.class)
public class ControllerTest {
//模拟http请求
private MockMvc mockMvc;
//用于将对象转换为json字符串
private ObjectMapper mapper = new ObjectMapper();
@Autowired
private WebApplicationContext context;
@Before
public void setUp(){
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
//测试数据获取
@Test
public void getPerson(){
try {
mockMvc.perform(MockMvcRequestBuilders
.get("/person/get/2018001") //请求的url,请求的方法是get
.accept(MediaType.APPLICATION_JSON_UTF8))
.andDo(print());//打印出请求和相应的内容
.andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串
} catch (Exception e) {
e.printStackTrace();
}
}
//测试数据的添加
@Test
public void addPerson(){
try {
mockMvc.perform(MockMvcRequestBuilders
.post("/person/add")
.param("name", "Apple") //添加参数
.accept(MediaType.APPLICATION_JSON_UTF8))
.andDo(print());
} catch (Exception e) {
e.printStackTrace();
}
}
//测试JSON字符串的保存
@Test
public void addPersonByJson(){
try {
Person person = new Person("Banana");
String requestBody = mapper.writeValueAsString(person);
mockMvc.perform(MockMvcRequestBuilders
.post("/person/addJson")
.contentType(MediaType.APPLICATION_JSON_UTF8) //数据的格式
.content(requestBody)
.accept(MediaType.APPLICATION_JSON_UTF8))
.andDo(print());
} catch (Exception e) {
e.printStackTrace();
}
}
}
- mockMvc.perform:执行一个RequestBuilder请求
- MockMvcRequestBuilders.get:构造一个get请求。另外提供了其他的请求的方法,如:post、put、delete等
- param:添加request的参数root的参数。假如使用需要发送json数据格式的时将不能使用这种方式,可见后面被@ResponseBody注解参数的解决方法
- contentType:指定传递的数据类型
- accept: 指定接受的数据类型
- andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台(对返回的数据进行的判断)
- andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理(对返回的数据进行的判断)
注意点
当使用JSON传递数据的时候,需要使用.contentType(MediaType.APPLICATION_JSON_UTF8).content(requestBody)的方式,
不然会发生org.springframework.http.converter.HttpMessageNotReadableException异常,因为相应方法只接受JSON数据格式。
RestTemplate方式
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.test.springboottest.bean.Person;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class ControllerRestTest {
@Value("http://localhost:${local.server.port}/person")
private String baseUrl;
private RestTemplate restTemplate = new RestTemplate();
@Test
public void getPerson(){
Person person=restTemplate.getForObject(baseUrl+"/get/001", Person.class);
System.out.println(person);
}
@Test
public void addPerson(){
//当直接传递参数需要用map
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("name", "Aster");
Person person=restTemplate.postForObject(baseUrl+"/add", paramMap, Person.class);
System.out.println(person);
}
@Test
public void addPersonByJson(){
try{
Person p = new Person("Banana");
Person person=restTemplate.postForObject(baseUrl+"/addJson", p, Person.class);
System.out.println(person);
}catch (Exception e) {
e.printStackTrace();
}
}
}
相比而言,RestTemplate比MockMvc更加简单,更加清晰。