基础框架:Springboot(版本信息:1.5.6.RELEASE)
环境信息:JDK1.8
测试jar包:spring-boot-starter-test
之前在其它项目见过使用Mock进行单元测试,SpringMvc环境下可以直接模拟请求进来Controller的测试,相比常用的Sping Junit和Spring TestNG等也有一定的可借鉴之处,
本篇结合相关资料进行Mock测试,对基本步骤和注意点以及一些不明白的地方做个笔记,后续项目中如果遇到可以加深理解。
一、基本的SpringBoot环境搭建好之后基本上会包含所需要的jar包,测试类可以直接在生成的src/main/test目录下新建
二、测试示例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class TestUserContorller {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGetUser() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/test/getUser.json").param("realName", "zhangsan")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
说明1:Spring4.2版本之后,已经用@SpringBootTest注解替换原先的注解,SpringMvc中会配置xml扫描来构建bean,SpringBoot中配置启动类即可以构建所有的bean,当然这个地方也可以只配置用到的bean
说明2:上述方式,适用于测试所有的Controller,一般测试单个Controller时都会推荐使用@SpringBootTest(classes = {MockServletContext.class}),然后构建MockMvc时使用mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); 其余的不变,对于请求测试的方法中不引用service bean的情况这种是可以的,但是若方法中涉及到service方法调用会抛出NullPonitException异常(@AutoWired注入的bean未初始化),目前还没找到解决办法,不过相信也是有解决方案的
附1:单个Controller测试完整示例
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {MockServletContext.class})
public class TestSimpleController {
private MockMvc mockMvc;
@Before
public void init() {
mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
}
@Test
public void testGetUser() throws Exception {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/test/kidding.json")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
System.out.println(result.getResponse().toString());
}
}
附2:Mock测试单个Controller
public class TestSimpleController {
/**
* 用于注解Mock对象具体要注入到的那个对象
* Controller类
*/
@InjectMocks
private UserController userController;
/**
* 用于注解在需要被Mock的对象上
* Controller类所需要引用的bean
*/
@Mock
private UserService userService;
private MockMvc mockMvc;
/**
* 初始化,模拟加载mvc的web测试环境
*/
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}
@Test
public void testGetUser() throws Exception {
User user = new User();
Mockito.when(userService.getUserByRealName("zhangsan")).thenReturn(user);
Assert.assertNotNull(user);
this.mockMvc.perform(MockMvcRequestBuilders.get("/test/getUser.json").param("realName", "zhangsan")
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
}
说明:测试过程中发现模拟请求以及传参都是正确的,不过如果service层里dao层的引用调用则不会执行到但是不会报错。