《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

相关文章
|
5天前
|
存储 监控 Java
JAVA线程池有哪些队列? 以及它们的适用场景案例
不同的线程池队列有着各自的特点和适用场景,在实际使用线程池时,需要根据具体的业务需求、系统资源状况以及对任务执行顺序、响应时间等方面的要求,合理选择相应的队列来构建线程池,以实现高效的任务处理。
81 12
|
2月前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
91 3
|
2月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
73 2
|
2月前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
47 2
|
3月前
|
Java 数据库
案例一:去掉数据库某列中的所有英文,利用java正则表达式去做,核心:去掉字符串中的英文
这篇文章介绍了如何使用Java正则表达式从数据库某列中去除所有英文字符。
82 15
|
3月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
28 1
|
3月前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
【10月更文挑战第8天】本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
51 5
|
Java
Java中需要注意的一些案例
Java中需要注意的一些案例
125 0
|
8天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
48 17