SpringBoot测试Controller层
⼀、准备⼯作
  1、导⼊测试依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
  2、Controller层:
@RestController("/")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping
public String index(){
return "Hello World!";
}
@GetMapping("/user")
public ResponseEntity<List<User>> listUser(){
List<User> list = new ArrayList<>();
list.add(new User(1,"张三"));
list.add(new User(2,"李四"));
return new ResponseEntity(list,HttpStatus.OK);
}
@GetMapping("/user/{userId}")
public ResponseEntity<User> getInfo(@PathVariable("userId") Integer userId){
User user  = userService.findByUserId(userId);
return new ResponseEntity(user,HttpStatus.OK);
}
}
  3、UserService实现如下:
@Service
public class UserServiceImpl implements UserService {
@Override
public User findByUserId(Integer userId) {
return new User(userId,"⽤户" + userId);
}
}
⼆、测试
  1、创建第⼀个测试⽤例:
    在类上添加@RunWith和@SpringBootTest表⽰是⼀个可以启动容器的测试类
@RunWith(SpringRunner.class)
@SpringBootTest //告诉SpringBoot去寻主配置类(例如使⽤@SpringBootApplication注解标注的类),并使⽤它来启动⼀个Spring application context;
public class UserController01Test {
@Autowired
private UserController userController;
//测试@SpringBootTest是否会将@Component加载到Spring application context
@Test
public void testContexLoads(){
Assert.assertThat(userController,notNullValue());
}
}
  2、Spring Test⽀持的⼀个很好的特性是应⽤程序上下⽂在测试之间缓存,因此如果在测试⽤例中有多个⽅法,或者具有相同配置的多个测试⽤例,它们只会产⽣启动应⽤程序⼀次的成本。使⽤@DirtiesContext注解可以清空缓存,让程序重新加载。
  将上⾯代码改造如下:在两个⽅法上都添加@DirtiesContext注解,运⾏整个测试类,会发现容器加载了两次。
  3、启动服务器对Controller进⾏测试:
    这种⽅式是通过将TestRestTemplate注⼊进来,进⾏发送请求测试,缺点是需要启动服务器。
@RunWith(SpringRunner.class)
//SpringBootTest.WebEnvironment.RANDOM_PORT设置随机端⼝启动服务器(有助于避免测试环境中的冲突)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
//使⽤@LocalServerPort将端⼝注⼊进来
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void greetingShouldReturnDefaultMessage() throws Exception {
Assert.ForObject("localhost:" + port + "/",String.class),
}
}
  4、使⽤@AutoConfigureMockMvc注解⾃动注⼊MockMvc:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc //不启动服务器,使⽤mockMvc进⾏测试http请求。启动了完整的Spring应⽤程序上下⽂,但没有启动服务器public class UserController02Test {
@Autowired
private MockMvc mockMvc;
/**
* .perform() : 执⾏⼀个MockMvcRequestBuilders的请求;MockMvcRequestBuilders有.get()、.post()、.put()、.delete()等请求。    * .andDo() : 添加⼀个MockMvcResultHandlers结果处理器,可以⽤于打印结果输出(MockMvcResultHandlers.print())。
* .andExpect : 添加MockMvcResultMatchers验证规则,验证执⾏结果是否正确。
*/
@Test
mvc的controllerpublic void shouldReturnDefaultMessage() throws Exception {
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}
  5、使⽤@WebMvcTest只初始化Controller层
@RunWith(SpringRunner.class)
//使⽤@WebMvcTest只实例化Web层,⽽不是整个上下⽂。在具有多个Controller的应⽤程序中,
// 甚⾄可以要求仅使⽤⼀个实例化,例如@WebMvcTest(UserController.class)
@WebMvcTest(UserController.class)
public class UserController03Test {
@Autowired
private MockMvc mockMvc;
@Test
public void shouldReturnDefaultMessage() throws Exception {
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}
  上⾯的代码会报错,因为我们使⽤@WebMvcTest只初始化Controller层,但是在UserController 中注⼊了UserService,所以报错。我们把代码注释如下,该测试就会成功了。   
  但是⼀般的Controller成都会引⽤到Service吧,怎么办呢,我们可以使⽤mockito框架的@MockBean注
解进⾏模拟,改造后的代码如下:
@RunWith(SpringRunner.class)
//使⽤@WebMvcTest只实例化Web层,⽽不是整个上下⽂。在具有多个Controller的应⽤程序中,
// 甚⾄可以要求仅使⽤⼀个实例化,例如@WebMvcTest(UserController.class)
@WebMvcTest(UserController.class)
public class UserController03Test {
@Autowired
private MockMvc mockMvc;
//模拟出⼀个userService
@MockBean
private UserService userService;
@Test
public void greetingShouldReturnMessageFromService() throws Exception {
//模拟userService.findByUserId(1)的⾏为
when(userService.findByUserId(1)).thenReturn(new User(1,"张三"));
String result = kMvc.perform(get("/user/1"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.name").value("张三"))
.andReturn().getResponse().getContentAsString();
System.out.println("result : " + result);
}
}
资料:
  json-path :
  mockito官⽹:
  spring官⽹⽤例:
  spring mockMvc⽂档:   

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。