前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速学会Springboot中编写Mock单元测试

快速学会Springboot中编写Mock单元测试

作者头像
码农小胖哥
发布2019-12-05 12:49:27
6.9K0
发布2019-12-05 12:49:27
举报
文章被收录于专栏:码农小胖哥的码农生涯

1.概要

软件测试是一个应用软件质量的保证。java开发者开发接口往往忽视接口单元测试。作为java开发如果会Mock单元测试,那么你的bug量将会大大降低。spring提供test测试模块,所以现在小胖哥带你来玩下springboot下的Mock单元测试,我们将对controller,service 的单元测试进行实战操作。

2.依赖引入

按照上面引入依赖而且scope为test。该依赖提供了一下类库

  • JUnit 4: 目前最强大的java应用单元测试框架
  • Spring Test & Spring Boot Test: Spring Boot 集成测试支持.
  • AssertJ: 一个java断言库,提供测试断言支持.
  • Hamcrest: 对象匹配断言和约束组件.
  • Mockito: 知名 Java mock 模拟框架.
  • JSONassert: JSON断言库.
  • JsonPath: JSON XPath 操作类库.

以上都是在单元测试中经常接触的类库。有时间你最好研究一下。

3.配置测试环境

一个Spring Boot 应用程序是一个Spring ApplicationContext ,一般测试不会超出这个范围。测试框架提供一个@SpringBootTest注解来提供SpringBoot单元测试环境支持。你使用的JUnit版本如果是JUnit 4不要忘记在测试类上添加@RunWith(SpringRunner.class),JUnit 5就不需要了。默认情况下,@SpringBootTest不会启动服务器。您可以使用其webEnvironment 属性进一步优化测试的运行方式,webEnvironment 相关讲解:

  • MOCK(默认):加载Web ApplicationContext并提供模拟Web环境。该选择下不会启动嵌入式服务器。如果类路径上没有Web环境,将创建常规非Web的ApplicationContext。你可以配合@AutoConfigureMockMvc或@AutoConfigureWebTestClient模拟的Web应用程序。
  • RANDOM_PORT:加载aWebServerApplicationContext并提供真实的Web环境,启用的是随机web容器端口。
  • DEFINED_PORT:加载WebServerApplicationContext并提供真实的Web环境 和RANDOM_PORT不同的是启用你激活的SpringBoot应用端口,通常都声明在application.yml配置文件中。
  • NONE:通过SpringApplication加载一个ApplicationContext。但不提供 任何 Web环境(无论是Mock或其他)。

注意事项:如果你的测试带有@Transactional注解时,默认情况下每个测试方法执行完就会回滚事务。但是当你的webEnvironment 设置为RANDOM_PORT或者 DEFINED_PORT,也就是隐式地提供了一个真实的servlet web环境时,是不会回滚的。这一点特别重要,请确保不会在生产发布测试中写入脏数据。

4.编写测试类测试你的api

言归正传,首先我们编写了一个BookService 作为Service 层

其实现类如下,为了简单明了没有测试持久层,如果持久层需要测试注意增删改需要Spring事务注解@Transactional支持以达到测试后回滚的目的。

controller层如下

我们在Spring Boot maven项目的单元测试包test下对应的类路径 编写自己的测试类

前两个注解不用说,第三个注解可能你们很陌生。这个是用来开启Mock Mvc测试的自动化配置的。 然后我们编写一个测试方法来测试BookApi#getBook(String title)接口。

简单讲解一下 MockMvc 执行一个模拟的get请求然后期望结果是expect Json字符串并且将相应对象打印了出来(下图1标识)。一旦请求不通过将抛出java.lang.AssertionError错误, 会把期望值(Expected)跟实际值打印出来(下图2标识)。如果跟预期相同只会出现下图1。

5.测试打桩

有个很常见的情形,在开发中有可能你调用的其他服务没有开发完,比如你有个短信发送接口还在办理短信接口手续,但是你还需要短信接口来进行测试。你可以通过@MockBean 构建一个抽象接口的实现。拿上面的BookService来说,假如其实现类逻辑还没有确定,我们可以通过规定其入参以及对应的返回值来模拟这个bean的逻辑,或者根据某个情形下进行某个路由操作的选择(如果入参是A则结果为B,如果为C则D)。这种模拟也被成为测试打桩。这里我们会用到Mockito 测试场景描述如下:

  • 指定打桩对象的返回值
  • 判断某个打桩对象的某个方法被调用及调用的次数
  • 指定打桩对象抛出某个特定异常

一般有以下几种组合:

  • do/when:包括doThrow(…).when(…)/doReturn(…).when(…)/doAnswer(…).when(…)
  • given/will:包括given(…).willReturn(…)/given(…).willAnswer(…)
  • when/then: 包括when(…).thenReturn(…)/when(…).thenAnswer(…)

其他都好理解,着重介绍一下Answer , Answer 正是为了解决如果入参是A则结果为B,如果为C则D这种路由操作的。接下来我们实操一下 ,跟最开始基本一样,只是更换成@MockBean

然后利用Mockito编写打桩方法,模拟上面BookServiceImpl 实现类。不过模拟的bean每次测试完都会自动重置。而且不能用于模拟在应用程序上下文刷新期间运行的bean的行为。

然后把这个方法注入controller 测试方法就可以测试了。

6.其他

内置的assertj也是常用的断言,api非常友好,这里也简单演示一下

7.总结

本文中实现了一些简单的Spring Boot启用集成测试。对测试环境的搭建,测试代码的编写进行了实战操作,基本能满足日常开发测试需要,相信你能从本文学到不少东西。相关的讲解代码可以从https://gitee.com/felord/mock-springboot获取。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档