目录
一 MockMvc 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
二 MockMvc 实现原理
MockMvcBuilder 是用来构造 MockMvc 的构造器,其主要有两个实现 : StandaloneMockMvcBuilder 和DefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成 Web 环境测试(此种方式并不会集成真正的 web 环境,而是通过相应的 Mock API 进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂 MockMvcBuilders 创建即可。
2.1 集成 Web 环境方式
MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定 WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的 MockMvc。
package com.sb;
import org.junit.Before;
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.SpringRunner;
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;
@RunWith(SpringRunner.class)
@SpringBootTest()
@WebAppConfiguration
public class ApplicationTests {
public MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Before()
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象
}
}
2.2 独立测试方式
MockMvcBuilders.standaloneSetup(Object... controllers):通过参数指定一组控制器,这样就不需要从上下文获取了。
package com.sb;
import org.junit.Before;
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.SpringRunner;
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;
@RunWith(SpringRunner.class)
@SpringBootTest()
@WebAppConfiguration
public class ApplicationTests {
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
}
}
个人建议使用集成 Web 环境方式:ApplicationTests 作为一个基类,所有的测试类都可以继承该基类。下面以第一种作为接口测试实现。
三 MockMvc 接口测试实现
3.1 controller 类
package com.sb.controller;
import com.sb.domain.User;
import com.sb.dto.RetDTO;
import com.sb.service.UserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.*;
@RestController
@RequestMapping(value="/users")
public class UserController {
@Resource
private UserService userService;
@RequestMapping(value="/insert", method=RequestMethod.POST)
public RetDTO insert(@RequestBody User user) {
return RetDTO.getReturnJson(userService.add(user));
}
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public RetDTO<User> getUser(@PathVariable Long id) {
return RetDTO.getReturnJson(userService.getUserById(id));
}
}
3.2 test 类
package com.sb.controller;
import com.alibaba.fastjson.JSON;
import com.sb.ApplicationTests;
import com.sb.domain.User;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
public class UserControllerTests extends ApplicationTests {
@Test
public void getUser() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/users/1"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print()).andReturn()
.getResponse()
.getContentAsString();
}
@Test
public void insert() throws Exception {
User user = new User();
user.setName("马六");
user.setAge(30);
mockMvc.perform(MockMvcRequestBuilders.post("/users/insert")
.contentType(MediaType.APPLICATION_JSON)
.content(JSON.toJSONString(user)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print()).andReturn()
.getResponse()
.getContentAsString();
}
}
3.3 运行结果
点击左上角绿色按钮 :
得到结果:
insert() 方法也是上述操作。
四 MockMvc 最佳实践总结
- 测试方法上必须使用 @Test 进行修饰。
- 测试方法必须使用 public void 进行修饰,不能带任何的参数。
- 新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开。
- 测试类所在的包名应该和被测试类所在的包名保持一致
- 测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖