## maven依赖
spring-boot-starter-test包含引入了JUnit。
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
```
## 注解介绍
* @RunWith(SpringRunner.class):指定JUnit使用Spring环境运行。SpringRunner 继承了SpringJUnit4ClassRunner,没有扩展任何功能,使用前者,名字简短而已。
* @SpringBootTest:会模拟SpringBoot应用启动,寻找带有SpringBootApplication的配置类启动,创建ApplicationContext容器。
* classes:此属性指定Spring Boot工程的启动类
* webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,指定一个随机端口,去启动内置的web应用服务器
* @WebMvcTest:只实例化Controller层,如果Controller层对Service层中有依赖关系,可以使用@MockBean注解进行模拟
* @LocalServerPort:该注解会把springboot内置web应用服务器启动端口赋给其注解的字段。
* @TestConfiguration:用它我们可以在一般的@Configuration之外补充测试专门用的Bean或者自定义的配置。
* @TestComponent:是另一种@Component,在语义上用来指定某个Bean是专门用于测试的。
* @MockBean:模拟Spring环境,解决测试中依赖问题,以下`@WebMvcTest使用`中即是@MockBean的经典使用
## @SpringBootTest使用
```
@RunWith(SpringRunner.class)
@SpringBootTest(classes = StartUpApplication.class,webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerTest {
@LocalServerPort
private int port;
private String baseUrl;
@Autowired
private TestRestTemplate restTemplate;
@BeforeEach
public void setUp(){
this.baseUrl="http://127.0.0.1:"+port;
}
@Test
public void index() {
System.out.println("request url is: "+baseUrl);
ResponseEntity<String> response = restTemplate.getForEntity(baseUrl, String.class);
System.out.println(response.getBody());
Assertions.assertEquals(response.getBody(),"Welcome to Spring Boot!");
}
}
```
## MockMvc详解
* 上面介绍的@SpringBootTest测试适合Service和DAO层方法的测试,不需要创建MockMvc
* 对Controller的方法进行测试,需要模拟HTTP环境,如果启动服务器,效率很低,Spring引入了MockMVC,实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用
* 注解:@AutoConfigureMockMvc,相当于new MockMvc
* 工具类:MockMvc(3步)
* perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;
* MockMvcRequestBuilders提供了get/post/put/delete/upload等http请求的方式
* 提供了header/contentType/cookie/characterEncoding/params等设置request参数的方式
* ResultActions
* andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确;
* andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台;
* andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理;
* MvcResult(自定义Assert)
* getModelAndView:获得控制层设置的ModeAndView对象
* getResponse:获得最终响应结果
```
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHello() throws Exception {
/*
* 1、mockMvc.perform执行一个请求。
* 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
* 3、ResultActions.param添加请求传值
* 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
* 5、ResultActions.andExpect添加执行完成后的断言。
* 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
* 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
* 7、ResultActions.andReturn表示执行完成后返回相应的结果,返回MvcResult。
*/
MvcResult result = mockMvc.perform(MockMvcRequestBuilders
.get("/hello")
// 设置返回值类型为utf-8,否则默认为ISO-8859-1
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
.param("name", "Tom"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("Hello Tom!"))
.andDo(MockMvcResultHandlers.print()).andReturn();
Assert.assertNotNull(result.getModelAndView().getModel().get("user"));
}
}
```
## @WebMvcTest使用
```
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
//模拟出一个userService
@MockBean
private UserService userService;
@Test
public void testService() throws Exception {
//模拟userService.findByUserId(1)的行为
when(userService.findByUserId(1)).thenReturn(new User(1,"张三"));
String result = this.mockMvc.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);
}
}
```