《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(6)

简介: 《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(6)

《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(5) https://developer.aliyun.com/article/1232054?groupCode=java



六、 如何测试链式调用


在日常编码过程中,很多人都喜欢使用链式调用,这样可以让代码变得更简洁。

 

 

 

1. 案例代码

 

这里,通过修改后的添加跨域支持代码来举例说明(原方法没有返回值)。


image.png

2. 方法1:普通测试法(不推荐)

 

正常情况下,每一个依赖对象及其调用方法都要mock,编写的代码如下:


/**
 * 跨域辅助测试类
 */
public class CorsHelperTest {
    /**
     * 测试: 添加跨域支持
     */
    @Test
    public void testAddCorsMapping() {
        // 模拟依赖方法
        CorsRegistry registry = Mockito.mock(CorsRegistry.class);
        CorsRegistration registration = Mockito.mock(CorsRegistration.class);
        Mockito.doReturn(registration).when(registry).addMapping(Mockito.anyString());
        Mockito.doReturn(registration).when(registration).allowedOrigins(Mockito.any());
        Mockito.doReturn(registration).when(registration).allowedMethods(Mockito.any());
        Mockito.doReturn(registration).when(registration).allowCredentials(Mockito.anyBoolean());
        Mockito.doReturn(registration).when(registration).maxAge(Mockito.anyLong());
        Mockito.doReturn(registration).when(registration).allowedHeaders(Mockito.any());
        // 调用测试方法
        Assert.assertEquals("跨域注册不一致", registration, CorsHelper.addCorsMapping(registry));
        // 验证依赖方法
        Mockito.verify(registry).addMapping("/**");
        Mockito.verify(registration).allowedOrigins("*");
        Mockito.verify(registration).allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS");
        Mockito.verify(registration).allowCredentials(true);
        Mockito.verify(registration).maxAge(3600L);
        Mockito.verify(registration).allowedHeaders("*");
    }
}

3. 方法2:利用RETURNS_DEEP_STUBS参数法(推荐)

 

对于链式调用,Mockito提供了更加简便的单元测试方法——提供Mockito.RETURNS_DEEP_STUBS参数,实现链式调用返回对象的自动mock。利用Mockito.RETURNS_DEEP_STUBS参数编写的测试用例如下:


/**
 * 跨域辅助测试类
 */
public class CorsHelperTest {
    /**
     * 测试: 添加跨域支持
     */
    @Test
    public void testAddCorsMapping() {
        // 模拟依赖方法
        CorsRegistry registry = Mockito.mock(CorsRegistry.class, Answers.RETURNS_DEEP_STUBS);
        CorsRegistration registration = Mockito.mock(CorsRegistration.class);
        Mockito.when(registry.addMapping(Mockito.anyString())
            .allowedOrigins(Mockito.any())
            .allowedMethods(Mockito.any())
            .allowCredentials(Mockito.anyBoolean())
            .maxAge(Mockito.anyLong())
            .allowedHeaders(Mockito.any()))
            .thenReturn(registration);
        // 调用测试方法
        Assert.assertEquals("跨域注册不一致", registration, CorsHelper.addCorsMapping(registry));
        // 验证依赖方法
        Mockito.verify(registry.addMapping("/**")
            .allowedOrigins("*")
            .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
            .allowCredentials(true)
            .maxAge(3600L))
            .allowedHeaders("*");
    }
}

 

代码说明:

 

在mock对象时,需要指定Mockito.RETURNS_DEEP_STUBS参数;

在mock方法时,采用when-then模式,when内容是链式调用,then内容是返回的值;

在verify方法时,只需要验证最后1次方法调用,verify内容是前n次链式调用;如果验证时某个方法调用的某个参数指定错误时,最后一个方法调用验证将因为这个mock对象没有方法调用而抛出异常。

 

4. 方法3:利用RETURNS_SELF参数法(推荐)

 

对于相同返回值的链式调用,Mockito提供了更加简便的单元测试方法——提供Mockito.RETURNS_SELF参数,实现链式调用返回对象的自动mock,而且还能返回同一mock对象。利用Mockito.RETURNS_SELF参数编写的测试用例如下:


image.png

代码说明:

 

在mock对象时,对于自返回对象,需要指定Mockito.RETURNS_SELF参数;

在mock方法时,无需对自返回对象进行mock方法,因为框架已经mock方法返回了自身;

在verify方法时,可以像普通测试法一样优美地验证所有方法调用。

 

方法对比:

 

普通测试法:mock调用方法语句较多;

利用RETURNS_DEEP_STUBS参数法:mock调用方法语句较少,适合于链式调用返回不同值;

利用RETURNS_SELF参数法:mock调用方法语句最少,适合于链式调用返回相同值。



《Java单元测试实战》——案例集锦:Java单元测试典型案例集锦(7) https://developer.aliyun.com/article/1232052?groupCode=java

相关文章
|
1天前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)
【7月更文挑战第3天】TestNG教程展示了如何自定义日志记录。首先创建一个名为`TestLog`的测试类,包含3个测试方法,其中一个故意失败以展示日志。使用`Assert.assertTrue`和`Reporter.log`来记录信息。接着创建`CustomReporter`类,继承`TestListenerAdapter`,覆盖`onTestFailure`, `onTestSkipped`, 和 `onTestSuccess`,在这些方法中自定义日志输出。
17 6
|
1天前
|
机器学习/深度学习 自然语言处理 Java
Java中的自然语言处理应用案例分析
Java中的自然语言处理应用案例分析
|
1天前
|
负载均衡 Java 微服务
Java中的可扩展微服务架构设计案例解析
Java中的可扩展微服务架构设计案例解析
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
Java中的自然语言处理应用案例分析
Java中的自然语言处理应用案例分析
|
2天前
|
负载均衡 Java 微服务
Java中的可扩展微服务架构设计案例解析
Java中的可扩展微服务架构设计案例解析
|
2天前
|
Java 测试技术 Android开发
《手把手教你》系列基础篇(八十四)-java+ selenium自动化测试-框架设计基础-TestNG日志-上篇(详解教程
【7月更文挑战第2天】TestNG是一个用于自动化测试的Java框架,提供日志记录功能。日志有两种模式:底层级详细记录每个步骤,高层级仅记录关键事件。示例代码展示了如何在测试方法中使用`Reporter.log()`记录信息,这些信息会显示在TestNG HTML报告中。文章还提及了日志显示时可能出现的编码问题及解决办法。
|
2天前
|
Java 测试技术 开发者
Java中设计可测试的代码的最佳实践
Java中设计可测试的代码的最佳实践
|
3天前
|
Java jenkins 持续交付
Jenkins是开源CI/CD工具,用于自动化Java项目构建、测试和部署。通过配置源码管理、构建触发器、执行Maven目标,实现代码提交即触发构建和测试
【7月更文挑战第1天】Jenkins是开源CI/CD工具,用于自动化Java项目构建、测试和部署。通过配置源码管理、构建触发器、执行Maven目标,实现代码提交即触发构建和测试。成功后,Jenkins执行部署任务,发布到服务器或云环境。使用Jenkins能提升效率,保证软件质量,加速上线,并需维护其稳定运行。
16 0
|
3天前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(八十三)-java+ selenium自动化测试-框架设计基础-TestNG测试报告-下篇(详解教程)
【7月更文挑战第1天】使用TestNG自定义报告的简要说明: - TestNG提供默认的HTML和XML报告,但可通过实现IReporter接口创建自定义报告。 - 自定义报告器类需扩展`CustomReporter.java`,实现`generateReport()`方法,接收XML套房、测试结果及输出目录作为参数。
14 0
|
3天前
|
Java 测试技术 Maven
如何使用Java进行单元测试
如何使用Java进行单元测试