目录

  • 为什么需要测试类
  • 常用的jar包
  • 测试模拟接口调用
  • 测试Restful接口
  • 通过Mock模拟方法调用结果
    • 判读方法调用次数
  • 注意事项

为什么需要测试类

  • 方便模拟验证已完成功能

    开发过程中,代码完成之后,在正式提交测试之前,往往需要自己对功能进行自查,修改一些明显的问题。但是有时候由于本地环境限制,实际流程和数据难以模拟,为了不影响其他模块,我们可以只针对自己新增加的功能进行测试。这时可以使用测试类,针对自己的接口,模拟特定的数据和环境,将测试的接口返回值与预期返回值进行对比,完成验证测试。

  • 方便后期维护

    由于项目开发过程中,经常有需求变更,有时候会有涉及范围很广的改动,有完善的测试类,可以在大面积改动的时候,检查出一些明显的问题,针对改动能对项目掌控的更好,节省测试时间,减少工作量。

常用的jar包

org.junit.* Junit4 框架

是通用的测试 java 程序的测试框架JUnit可以对Java代码进行白盒测试。
org.junit.Assert.* 断言,用于对比结果是否符合预期,用来判断测试结果的常用框架

org.mockito.* mock

也叫打桩,用来模拟数据,模拟方法调用


下面以SpringBoot为例,展示下测试类的具体使用


测试模拟接口调用

有接口 TestService 参数为String name 返回结果是 "Hello " + name

@Service
public class TestServiceImpl implements TestService {/*** 测试接口*/@Overridepublic String testInterface(String name) {return "Hello " + name;}
}

这是我们的测试类

@RunWith(SpringRunner.class)
@ActiveProfiles("ut")
@SpringBootTest
public class SiteCacheTest extends BaseTest {@Autowiredprivate TestService testService ;@Testpublic void testInterface() {String result = testService.testInterface("Tom");Assert.assertEquals("Hello Tom", result );}
}

测试结果是运行成功,这是一个很简单的例子,没有复杂的参数和业务逻辑,接口内部也没有对其他接口的调用。
在这个测试类中
@ActiveProfiles(“ut”) 表示该测试运行时使用的是 application-ut.properties配置文件,我们实际开发工作中,往往会有多个环境,可以给测试类指定环境,方便控制测试,以及防止测试数据对实际环境造成影响。
@SpringBootTest 该注解表示这个类是一个SpringBoot测试类
Assert.assertEquals(“Hello Tom”, result )
该方法接收两个参数,前者为期望值,后者为实际值,如果不一致,会测试失败
Assert还有很多类似的方法,常用的有
1 - Assert.fail()

让测试直接出错,抛出 AssertionError 。

2 - Assert.fail(String message)

让测试直接出错,并在抛出 AssertionError 时输出 message 作为错误提示信息。

3 - Assert.assertNull(Object object)

猜测 object 为 null,如果不为 null ,抛出 AssertionError 。

4 - Assert.assertSame(Object expected, Object actual)

猜测 expected 对象和 actual 对象引用的是同一个对象。 如果不同,抛出 AssertionError 。

5 - Assert.assertNotSame(Object expected, Object actual)

猜测 expected 对象和 actual 对象引用不同的对象。 如果相同,抛出 AssertionError 。

6 - Assert.assertTrue(boolean condition)

猜测 condition 为 true 。 如果为 false ,抛出 AssertionError 。

7 - Assert.assertFalse(boolean condition)

猜测 condition 为 false 。 如果为 true , 抛出 AssertionError 。

8- Assert.assertEquals(long expected, long actual)

猜测两个 long 类型 expected 和 actual 的值相等。 如果不相等,抛出 AssertionError 。

9 - Assert.assertNotEquals(long unexpected, long actual)

猜测两个 long 类型 unexpected 和 actual 的值不相等。 如果相等,抛出 AssertionError 。

测试Restful接口

前后台返利开发中,针对给前台调用的接口,经常会有一些500错误等,可以模拟请求,根据接口路径来模拟前端调用
通常会传一些错误参数来验证返回错误信息的情况。

@ActiveProfiles("ut")
@RunWith(SpringRunner.class)
@SpringBootTest
public class ControllerTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mvc;@Beforepublic void setUp() {mvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象}@Testpublic void testController() throws Exception {String json = "{\n" +"\t\"username\": \"admin\",\n" +"\t\"password\": \"1234\"\n" +"}";String json1 = "{\n" +"\t\"username\": null,\n" +"\t\"password\": \"1234\"\n" +"}";mvc.perform(MockMvcRequestBuilders.post("/test/login").contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON_UTF8).content(json1.getBytes()))//传json参数.andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());mvc.perform(MockMvcRequestBuilders.post("/test/login").contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON_UTF8).content(json.getBytes()))//传json参数.andExpect(MockMvcResultMatchers.status().isInternalServerError()).andDo(MockMvcResultHandlers.print());}}

如上,我们传正常的参数时,期望返回200, 即 MockMvcResultMatchers.status().isOk()
传参数错误时返回 500, 即MockMvcResultMatchers.status().isInternalServerError()

在这个测试类中
首先需要引入WebApplicationContext 用来模拟前台接口调用

@Before 该注解注解的方法,会在测试运行之前先运行,一般用于准备测试数据,初始化对象等,在此例中,我们用来初始化测试用的MockMvc 对象。
@Autowired 测试类可以像正常的类一样,注入你所需要的对象
MockMvcRequestBuilders 来指定测试接口路径,以及请求方式
.andExpect 类似断言, 来指定期望值。

通过Mock模拟方法调用结果

在开发过程中,类都不是独立的,往往一个方法的实现,需要调用多个不同地方的方法组合来实现一个功能,在测试中,我们需要其他方法的返回值满足我们的测试需要,这个时候可以使用@Spy注解来包装某个类,控制它的方法返回值。
下面看例子

@RunWith(SpringRunner.class)
@ActiveProfiles("ut")
@SpringBootTest
public class MockTest {@Spy@Autowiredprivate TestService testService;@Beforepublic void setUp() {MockitoAnnotations.initMocks(this);}@Testpublic void codeTest() {Mockito.when(testService.getUUID()).thenReturn("cdc60ad5609ddced1b128c60ac92340d");}}

在这个测试类中,testService中存在一个方法getUUID(),是返回随机id的,但是在我们要测试的方法中调用了这个方法,我们需要用到这个uuid,来模拟数据,以便测试我们的接口,比如我们需要根据它去另外一张表查询数据,但是我们不知道调用时随机的uuid是什么,这时候可以指定它的返回值,当testService.getUUID()被调用时,返回一个指定的值,这样我们就可以继续操作了。

@Spy 对一个注入的类进行包装,以便可以模拟方法返回值
我们需要使用 MockitoAnnotations.initMocks(this); 来初始化对象,该方法会对使用了**@Spy**的类进行初始化。
然后我们可以针对初始化过的对象来模拟返回值。

Mockito.when(xxx).thenReturn(xxx);
从字面可以看出,当…的时候返回…
需要注意的是when(…) thenReturn(…)会调用真实的方法,如果你不想调用真实的方法而是想要mock的话
就使用 doReturn(…) when(…) 不会调用真实方法

判读方法调用次数

有些时候针对循环和和判断较多,或者业务逻辑较为复杂的场景,需要判断方法调用次数。 还有一个场景是判断缓存是否生效,对于加了缓存的方法,多次调用,一般只有一次实际的调用,可以用这个方法来判断调用次数。

@RunWith(SpringRunner.class)
@ActiveProfiles("ut")
@SpringBootTest
public class CallTimesTest {@MockBeanprivate TestDao testDao;@Autowiredprivate TestService testService;@Testpublic void testCallTimes() {//设置第一次返回,第二次返回when(testDao.findUserByName(1)).thenReturn("user1").thenReturn("user2");String user1 = testService.findUserByName(1);Assert.assertEquals("user1", user1);String user2 = testService.findUserByName(1);Assert.assertEquals("user1", user1);verify(testDao, times(1)).findWithFullNameByTaskId(1);}

假设 testService 的findUserByName 方法内部是调用的 testDao的findUserByName方法,我们首先使用**@MockBean** 注解 注解testDao ,对其进行包装,然后我们可以对其进行模拟 ,设置第一次调用返回user1,第二次调用返回user2, 然后testService调用两次,如果在testDao的findUserByName方法上加了缓存,那么对于同样的入参,实际上只会调用一次。
我们可以使用verify来验证方法调用次数。

需要注意的是,findUserByName 方法这里我们的入参是1,在mock中我们有时候不需要写死参数,而是符合一定条件的参数即可,mock提供了一系列方法指定参数,如下图

注意事项

  • 测试要注意覆盖率,不要只测试正确的情况,也要测试异常的情况
  • 要模拟方法调,设定返回值需要先对类进行包装,@Mock 和@Spy注解均可以实现,区别在于前者是虚假的调用,而且不能mock自动装配的Bean,需要和@InjectMock配合使用;而后者监测真实的调用,方法实际上真的调用了,使用时要注意,想要不调用,可以使doReturn(…) when(…)。
  • 在maven项目中,不设置skiptest=true的话,在打包时会默认先执行一遍测试类,所以要注意设置测试类运行环境,以免测试数据对正式环境造成污染,导致不必要的错误,更为规范的做法是,在每个测试用例中,最后对测试数据进行删除。

测试类写法以及几种常用方式相关推荐

  1. java 解析/操作 xml 几种常用方式 xml的增加/删除/修改

    java 解析/操作 xml 几种常用方式 xml的增加/删除/修改 首先,我们先介绍几种常用的xml解析器. 1. 介绍 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方 ...

  2. Ngnix安装的几种常用方式

    Ngnix安装的几种常用方式 本文介绍了如何安装NGINX开源. 在稳定版还是主线版之间进行选择 在预编译的程序包和从源代码进行编译之间进行选择 安装预编译包 预建套件中包含的模块 安装预建的Cent ...

  3. 文件操作的几种常用方式

    文件操作的几种常用方式,看起来有很多类型,然而无非是三种,读(r),写(w),追加(a),主要简单介绍下这几种常用方式. 更多学习链接:https://www.nhooo.com/python/pyt ...

  4. 【方法整理】Oracle 获取trace跟踪文件名的几种常用方式

    [方法整理]Oracle 获取trace跟踪文件名的几种常用方式 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其 ...

  5. Silve37.Silverlight和ASP.NET相互传参的两种常用方式(QueryString,Cookie)

    在本节中将讲述Silverlight和ASP.NET页面的相互传参的两种常用方式:Cookie和QueryString.首先我们新建一个名 为SLConnectASP.NET的Silverlight应 ...

  6. Windows校验文件哈希hash的两种常用方式

    大家经常都到哪儿去下载软件和应用程序呢?有没想过下载回来的软件.应用程序或资源是否安全呢?在 Windows 10 和 Office 2016 发布当初,很多没权限的朋友都使用第三方网站去下载安装映像 ...

  7. it有啥好咨询的_蓝盟浅析,IT外包的四种常用方式

    IT外包服务主要分为IT运维外包和软件开发外包,对于软件开发外包主要偏于研发类型,在本文中主要讨论IT运维外包. 上海蓝盟认为,IT运维外包主要包含IT服务外包.IT采购.弱电工程.系统集成和云服务等 ...

  8. html中img显示图片的两种常用方式

    html中img显示图片的两种常用方式 显示图片,尤其是二维码的时候,大都是自动生成的,所以就需要能够从后台返回字符串,前台浏览器进行解析.好了,下面是这两种方式. 1. <img src=&q ...

  9. asp.net html silverlight 传参数,Silverlight和ASP.NET相互传参的两种常用方式(QueryString,Cookie)...

    Silverlight实用窍门系列:37  程兴亮,网名煦风满裳 在本节中将讲述Silverlight和ASP.NET页面的相互传参的两种常用方式:Cookie和QueryString.首先我们新建一 ...

  10. python 读写数据文件的6种常用方式

    本文主要介绍python读写数据文件的6种常用方式. 1. python内置方法 with open(r'test.xlsx') as f:a = f.read() 一般,在应用上述上下文管理器后,可 ...

最新文章

  1. Csharp: 拼音转汉字字符搜索字符串
  2. PowerShell批量设置PATH环境变量
  3. OutOfRangeError closed and has insufficient elements (requested 512, current size 362)
  4. GDCM:gdcm::Version的测试程序
  5. python中函数定义可以不包括什么_Python 中,函数定义可以不包括以下_______。
  6. Javascript学习数据结构--集合(Set实现)
  7. faster rcnn论文_论文导读-从Faster-RCNN/Mask RCNN/Cascade-RCNN到HTC
  8. 融云联合ofo给大家送福利!
  9. mysql 纯真ip 导出dat_纯真IP数据库(qqwry.dat)转换成最新的IP数据库格式(ipwry.dat)
  10. 盘点python socket 中recv函数的坑
  11. 设置div背景颜色透明度,内部元素不透明
  12. 指数分布的样本和是充分统计量
  13. 人生的第一篇博客φ(>ω<*)
  14. 使用‘终端’融合磁盘然后进行MAC重装系统
  15. 2021-09-29破解小米“铁蛋”,只需9999元,你也可以做一个四足机器人!
  16. 一元二次求解matlab程序,规范MATLAB编程实例——求解一元二次方程
  17. 石墨文档(协同开发)
  18. (数字ic验证)从零开始的apb_watchdog验证模块搭建(一、功能介绍与环境搭建)
  19. 【哈希】购物券(bday)
  20. 鸡兔同笼python程序怎么写_【鸡】鸡的功效_鸡图片_食材百科_美食杰

热门文章

  1. Java扫雷游戏的设计与实现毕业设计论文
  2. 【测绘程序设计】C#将度分秒(° ‘ “)转换度(°)程序实现(附源码)
  3. Java自学路线图之Java进阶自学
  4. win10 Visio软件运行 闪退
  5. 求 s = a+aa+aaa+… …+aaa…a的值,其中a是一个数字
  6. 【ArcGIS教程03】基础知识(建议收藏)
  7. 【小程序demo】带你玩转支付宝小程序之小程序二维码
  8. 水系图一般在哪里找得到_如何对于排水系统的服务范围进行统计分析
  9. 点云 数据 (偏向于研究大小)
  10. apache comments io包IOUtils方法简单介绍