一、准备工作

  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.assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/",String.class),
Matchers.containsString("Hello World"));
}
}

  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
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/"))
.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 {
this.mockMvc.perform(get("/"))
.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 = 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);
} }

 

资料:

  json-path : https://github.com/json-path/JsonPath

  mockito官网:https://site.mockito.org/

  spring官网用例:https://spring.io/guides/gs/testing-web/

  spring mockMvc文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html

   

SpringBoot测试Controller层的更多相关文章

  1. 【异常处理】Springboot对Controller层方法进行统一异常处理

    Controller层方法,进行统一异常处理 提供两种不同的方案,如下: 方案1:使用 @@ControllerAdvice (或@RestControllerAdvice), @ExceptionH ...

  2. Springboot对Controller层方法进行统一异常处理

    Controller层方法,进行统一异常处理 提供两种不同的方案,如下: 方案1:使用 @@ControllerAdvice (或@RestControllerAdvice), @ExceptionH ...

  3. PowerMock+SpringMVC整合并测试Controller层方法

    PowerMock扩展自Mockito,实现了Mockito不支持的模拟形式的单元测试.PowerMock实现了对静态方法.构造函数.私有方法以及final方法的模拟支持,对静态初始化过程的移除等强大 ...

  4. Junit mockito 测试Controller层方法有Pageable异常

    1.问题 在使用MockMVC+Mockito模拟Service层返回的时候,当我们在Controller层中参数方法调用有Pageable对象的时候,我们会发现,我们没办法生成一个Pageable的 ...

  5. junit基础学习之-测试controller层(2)

    准备工作: eclipse本身带有junit4,可以直接build path,加入junit. 连接数据库的配置文件需要修改,之前的文件是采用properties+xml文件的形式,但是在测试的时候因 ...

  6. springboot测试service层的单元测试

    package com.test.service; import com.task.Application;import com.task.model.po.TaskRecordDo;import o ...

  7. 使用Mock 测试 controller层

    package action; import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import ...

  8. ssm框架中Controller层的junit测试_我改

    Controller测试和一般其他层的junit测试可以共用一个BaseTest 一.BaseTest如下: @RunWith(SpringJUnit4ClassRunner.class) @WebA ...

  9. Spring MVC如何测试Controller(使用springmvc mock测试)

    在springmvc中一般的测试用例都是测试service层,今天我来演示下如何使用springmvc mock直接测试controller层代码. 1.什么是mock测试? mock测试就是在测试过 ...

随机推荐

  1. C 风格字符串、string 类要点总结

    1. C风格字符串 1.1 其它 头文件<cstring> 特殊性质:C风格字符串以空字符\0结尾 1.2 读取一行的区别 1.2.1 cin.getline(array1,n,char) ...

  2. 45 容器(四)——手写LinkedList

    概念 LinkedList级双向链表,它的单位是节点,每一个节点都要一个头指针和一个尾指针,称为前驱和后继.第一个节点的头指针指向最后一个节点,最后一个节点的尾指针指向第一个节点,形成环路. 链表增删 ...

  3. Nginx 配置 HTTP 跳转 HTTPS-Linux运维日志

    本文介绍 Nginx 访问 HTTP 跳转 HTTPS 的 4 种配置方式. rewrite Nginx rewrite 有四种 flag: break:在一个请求处理过程中将原来的 url 改写之后 ...

  4. windows10环境下的RabbitMQ安装_笔记

    原文:https://blog.csdn.net/weixin_39735923/article/details/79288578 第一步:下载并安装erlang原因:RabbitMQ服务端代码是使用 ...

  5. Future Failure CodeForces - 838C (博弈论,子集卷积)

    大意: 两人轮流操作一个长$n$, 只含前$k$种小写字母的串, 每次操作删除一个字符或者将整个串重排, 每次操作后得到的串不能和之前出现过的串相同, 求多少种串能使先手必胜. 找下规律发现$n$为奇 ...

  6. WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆。

    原文:WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆. 最近总是收到一个异常 "System.Inva ...

  7. .net语音播放,自定义播报文字

    // using System.Speech.Synthesis; SpeechSynthesizer synth = new SpeechSynthesizer(); // Configure th ...

  8. 支持移动端裁剪图片插件Jcrop(结合WebUploader上传)

    (此教程包括前端实现图片裁剪,后端进行获取裁剪区并保存) 最近有一个需求,微信公众号上传图片,支持自定义裁剪. 以前用过一款裁剪插件cropper,很久没用了,不知道对移动端操作兼容如何,重新从网上搜 ...

  9. C#混音同时录制采集声卡和麦克风话筒

    在项目中,我们可能需要同时录制声卡的声音和麦克风的声音,比如直播间,在线教学.那么如何实现呢?当然是采用SharpCapture!下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步: ...

  10. webpack--splitChunksPlugin配置学习随笔

    该配置用于代码抽离.官方文档 官方默认配置: module.exports = { //... optimization: { splitChunks: { chunks: 'async', // 异 ...