本文主要功能:

对最简单的/hello接口,如何编写单元测试用例。

1、首先,要引入以下依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

2、下面,我们来编写测试类

方式一、restTemplet远程调用

如果你的服务部署在远端Linux服务器上,通过本地单元测试用例,调接口,你可以通过以下方式:

首先,你在Linux服务器启动你的服务,可以看到服务端口为8888



然后,撰写代码

/**
* @program: helloword
* @description: <description>
* @author: cavan
* @create: 2021-11-30 21:36
*/
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class RestemplateTest { private final static String url = "http://121.43.225.17:8888/hello"; private static RestTemplate restTemplate = new RestTemplate(); /**
* 前置步骤
*/
@Before
public void setUp() {
} @Test
public void test() {
ResponseEntity<String> response = restTemplate.exchange(url,
HttpMethod.GET,
new HttpEntity(null),
String.class);
Assert.assertEquals("hello world", response.getBody());
Assert.assertEquals(response.getStatusCodeValue(), 200);
} /**
* 后置步骤
*/
@After
public void tearDown() {
}
}

结果Pass,

方式二、使用mock方式单元测试

Spring测试框架提供MockMvc对象,可以在不需要客户端-服务端请求的情况下进行MVC测试,完全在服务端这边就可以执行Controller的请求,跟启动了测试服务器一样。

测试开始之前需要建立测试环境,setup方法被@Before修饰。通过MockMvcBuilders工具,使用WebApplicationContext对象作为参数,创建一个MockMvc对象。最后获取到MockServletContext这个上下文就可以进行测试了

代码如下:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class HellowordApplicationTests {
private MockMvc mockMvc; @Autowired
private WebApplicationContext context; /**
* 前置步骤
*/
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
// mockMvc = MockMvcBuilders.standaloneSetup((new HelloWord())).build();
} @Test
public void contextLoads() 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()输出整个响应结果信息。
* 5、ResultActions.andReturn表示执行完成后返回相应的结果。
*/
MvcResult mvcResult =
mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
Assert.assertEquals(200, mvcResult.getResponse().getStatus());
Assert.assertEquals("hello world", mvcResult.getResponse().getContentAsString());
} /**
* 后置步骤
*/
@After
public void tearDown() {}
}

结果,pass

过程中出现的问题记录:

启动测试类的时候出现如下报错,



错误代码如下

org.junit.runners.model.InvalidTestClassError: Invalid test class 'com.cavan.helloword.MockTests':
1. No runnable methods at org.junit.runners.ParentRunner.validate(ParentRunner.java:525)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:92)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:74)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:137)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder.buildRunner(DefensiveAllDefaultPossibilitiesBuilder.java:114)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder.runnerForClass(DefensiveAllDefaultPossibilitiesBuilder.java:57)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
at org.junit.vintage.engine.discovery.ClassSelectorResolver.resolveTestClass(ClassSelectorResolver.java:66)
at org.junit.vintage.engine.discovery.ClassSelectorResolver.resolve(ClassSelectorResolver.java:47)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:134)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:185)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:125)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.access$100(EngineDiscoveryRequestResolution.java:57)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext.resolve(EngineDiscoveryRequestResolution.java:224)
at org.junit.vintage.engine.discovery.MethodSelectorResolver.resolveParentAndAddFilter(MethodSelectorResolver.java:56)
at org.junit.vintage.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:40)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:146)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:185)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:125)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:91)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:82)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:113)
at org.junit.vintage.engine.discovery.VintageDiscoverer.discover(VintageDiscoverer.java:44)
at org.junit.vintage.engine.VintageTestEngine.discover(VintageTestEngine.java:63)
at org.junit.platform.launcher.core.DefaultLauncher.discoverEngineRoot(DefaultLauncher.java:181)
at org.junit.platform.launcher.core.DefaultLauncher.discoverRoot(DefaultLauncher.java:168)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

经过定位发现,导入的Test包错误,这是我导入的包路径:import org.junit.jupiter.api.Test;

正确的路径:import org.junit.Test;

注意:重点注意下,@RunWith()这个注释一定要有,因为调用controller方法需要重启一个controller,要运行,就需要一个端口,这个可以随机开启一个端口供测试用。

本文Gitee代码链接:https://gitee.com/cavan2021/springboot/tree/master/helloword

参考:https://blog.csdn.net/qq_44014971/article/details/108056557

SpringBoot系列(六)如何使用 MockMvc 或者 RestTemplate 发请求进行单元测试的更多相关文章

  1. springboot系列六、springboot配置错误页面及全局异常

    一.spring1.x中处理方式 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new ...

  2. SpringBoot系列六:SpringBoot整合Tomcat

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合 Tomcat 2.背景 SpringBoot 本身支持有两类的 WEB 容器:默认的 To ...

  3. SpringBoot系列: 单元测试

    SpringBoot 项目单元测试也很方便, Web项目中单元测试应该覆盖:1. Service 层2. Controller 层 本文前半部分讲解是一些测试基础配置. 对于Service和Contr ...

  4. SpringBoot系列(一)RestTemplate

    作为springBoot的开篇系列,RestTemplate只能表示我只是个意外 what RestTemplate是spring提供的用于访问rest服务的客户端(其实类似Apache的HttpCl ...

  5. SpringBoot系列: RestTemplate 快速入门

    ====================================相关的文章====================================SpringBoot系列: 与Spring R ...

  6. SpringBoot系列(六)集成thymeleaf详解版

    SpringBoot系列(六)集成thymeleaf详解版 1. thymeleaf简介  1. Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎.  2. Thymeleaf ...

  7. springBoot系列-->springBoot注解大全

    一.注解(annotations)列表 @SpringBootApplication:包含了@ComponentScan.@Configuration和@EnableAutoConfiguration ...

  8. SpringBoot系列——Security + Layui实现一套权限管理后台模板

    前言 Spring Security官网:https://spring.io/projects/spring-security Spring Security是一个功能强大且高度可定制的身份验证和访问 ...

  9. SpringBoot系列之集成logback实现日志打印(篇二)

    SpringBoot系列之集成logback实现日志打印(篇二) 基于上篇博客SpringBoot系列之集成logback实现日志打印(篇一)之后,再写一篇博客进行补充 logback是一款开源的日志 ...

  10. SpringBoot图文教程17—上手就会 RestTemplate 使用指南「Get Post」「设置请求头」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1-Spr ...

随机推荐

  1. 力扣626(MySQL)-换座位(中等)

    题目: 表: Seat 编写SQL查询来交换每两个连续的学生的座位号.如果学生的数量是奇数,则最后一个学生的id不交换. 按 id 升序 返回结果表. 查询结果格式如下所示. 示例1: 解释: 请注意 ...

  2. 力扣183(MySQL)-从不订购的客户(简单)

    题目: 某网站包含两个表,Customers 表和 Orders 表.编写一个 SQL 查询,找出所有从不订购任何东西的客户. Customers 表: Orders 表:  解题思路: 需要查询出没 ...

  3. 科普达人丨漫画图解什么是eRDMA?

    简介: 绕过CPU,将数据直接从一台计算机的内存传输到另一台计算机,进行网络加速 在一个领先的阿里云数据中心里,数百台服务器(也就是大型的计算机)在疯狂工作和通信,他们正在合力完成一个大型的大数据处理 ...

  4. Hexo博客框架—轻量、一令部署

    ​简介:Hexo 是一个快速.简洁且高效的博客框架.Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页.Hexo支持Github Flavored M ...

  5. [GPT] export, export default, import, module.exports, require

    ES6 规范:export 和 import 配对 import 的 {} 大括号里面指定要从其他模块导入的变量名, 如果 export 命令没有写 default,那么 import {} 大括号里 ...

  6. dotnet 使用 ConfigureAwait.Fody 库设置默认的 await 同步上下文切换配置

    在 dotnet 里面,使用 await 进行异步逻辑,默认是会尝试切换回调用 await 的线程同步上下文.这个机制对于大多数的上层应用来说都是符合逻辑且方便的逻辑,例如对于带 UI 线程的 WPF ...

  7. 2018-11-23-国内好用的-DNS-列表

    title author date CreateTime categories 国内好用的 DNS 列表 lindexi 2018-11-23 12:45:57 +0800 2018-11-23 12 ...

  8. 如何在局域网内两台电脑上进行webapi的在线调试

    原文地址:https://www.zhaimaojun.top/Note/5475298(我自己的博客) 局域网内WebApi的远程调试方法: 第一步:管理员方式运行Vs并打开需要运行的项目,如果已经 ...

  9. ruby 常用代码片段

    # 文件的当前目录 puts __FILE__ # string.rb # 文件的当前行 puts __LINE__ # 6 #文件的当前目录 puts __dir__ #/media/haima/3 ...

  10. BIN文件格式

    BIN文件里面包含的只有代码生成的机器码,不像ELF文件或者obj文件一样还包含其他东西.MS-DOS.设备驱动文件以及操作系统的bootloader文件都是BIN文件. 在NASM中,BIN文件默认 ...