【Java】CompletableFuture+Mockito单元测试不通过 Unnecessary stubbings detected

news/2024/7/8 9:16:41 标签: 单元测试, log4j, java

文章目录

  • 问题描述
  • 问题分析
  • 解决
      • Thread.sleep
      • get()
      • Mockito.lenient()

问题描述

有个接口使用CompletableFuture实现的异步调用,现在要用Mockito写单元测试

java">	@Test
    public void updateNumAsync() {
        Integer newNum = 600;
        // updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据
        // 生成要用的stub
        when(ApiUtil.put(Constants.UPDATE_COUNT, newNum.toString(), serverId)).thenReturn("{\"code\":0}");
        App.updateNumAsync(serverId, newNum).whenComplete((result, throwable) -> {
            assertEquals(result.getCode(), 0);
        });
    }

结果测试不通过:

Tests Failed: 1 of 1 test
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.

问题分析

看控制台输出的意思大概就是when(...).return(...) mock的stub没被用到,然后测试不通过。
因为测试过程主要就是:1)mock一个要用的stub; 2)调用待测接口;3)检查结果。由于这里是异步调用,updateNumAsync里调用的CompletableFuture.supplyAsync()用的ForkJoinPool,会有一个线程1在后台异步执行updateNum的操作,因此猜测可能是当前test的线程0在异步过程中先结束了,导致线程0 Mock的stub并没有被线程1执行的待测试接口用到,导致Tests Failed

解决

Thread.sleep

既然Test的线程0结束的太早,那么强行让他多等一会是不是就好了?

java">	@Test
    public void updateNumAsync() throws InterruptedException {
        Integer newNum = 600;
        // updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据
        // 生成要用的stub
        when(ApiUtil.put(Constants.UPDATE_COUNT, newNum.toString(), serverId)).thenReturn("{\"code\":0}");
        App.updateNumAsync(serverId, newNum).whenComplete((result, throwable) -> {
            assertEquals(result.getCode(), 0);
        });
        Thread.sleep(1000L);
    }

结果测试通过,证明之前的猜想应该是对的。但不太推荐这样做。

Tests Passed: 1 of 1 test

get()

CompletableFuture通过get()获取异步调用结果时,会阻塞当前线程直到异步操作结束返回。也就是说test的线程0不会提早结束,导致虚拟机栈中的stub在被线程1 调用之前被回收。

java">	@Test
    public void updateNumAsync() throws  InterruptedException, ExecutionException {
        Integer newNum = 600;
        // updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据
        // 生成要用的stub
        when(ApiUtil.put(Constants.UPDATE_COUNT, newNum.toString(), serverId)).thenReturn("{\"code\":0}");
        App.updateNumAsync(serverId, newNum).whenComplete((result, throwable) -> {
            assertEquals(result.getCode(), 0);
        }).get();
    }

结果测试通过.

Tests Passed: 1 of 1 test

Mockito.lenient()

stackoverflow上面有人在mock多个stub的同时(用了get()),但也还会出现Unnecessary stubbings detected.,详情可以看原帖。大概就是有时Mockito可能没有按照确定的顺序调用这些方法,此时就可以用lenient()
这个方法在前面那个问题里也是能让测试通过的。

java">	@Test
    public void updateNumAsync(){
        Integer newNum = 600;
        // updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据
        // 生成要用的stub
        Mockito.lenient().when(ApiUtil.put(Constants.UPDATE_COUNT, newNum.toString(), serverId)).thenReturn("{\"code\":0}");
        App.updateNumAsync(serverId, newNum).whenComplete((result, throwable) -> {
            assertEquals(result.getCode(), 0);
        });
    }

具体原理还不是很明白,反正就是能work,先埋个坑,之后有空再看看⑧


http://www.niftyadmin.cn/n/5536921.html

相关文章

【免费资料】IEEE33节点系统参数及拓扑图visio

主要内容 对于初学配电网的同学,最经典的系统即是33节点配电网系统,在各个研究文献中出现频次最高的也是这个系统,为了让大家更好了解33节点系统参数,本次整理了系统节点、支路参数excel以及33节点网络拓扑图visio&#xff0c…

二维舵机颜色追踪,使用树莓派+opencv+usb摄像头+两个舵机实现颜色追踪,采用pid调控

效果演示 二维云台颜色追踪 使用树莓派opencvusb摄像头两个舵机实现颜色追踪,采用pid调控 import cv2 import time import numpy as np from threading import Thread from servo import Servo from pid import PID# 初始化伺服电机 pan Servo(pin19) tilt Serv…

累积分布函数的一些性质证明

性质1: E [ X ] ∫ 0 ∞ ( 1 − F ( x ) ) d x − ∫ − ∞ 0 F ( x ) d x ( 1 ) E[X]\int_0^{\infty}(1-F(x))dx - \int_{-\infty}^0F(x)dx\quad (1) E[X]∫0∞​(1−F(x))dx−∫−∞0​F(x)dx(1) 证明: E [ X ] ∫ − ∞ ∞ x p ( x ) d x E[X] …

达梦数据库小技巧

达梦数据库小技巧 一: 时间类型TIMESTAMP使用1.1 建表1.2 插入1.3按时间戳查询,返回某一列不重复的值 二:存储过程创建和调用2.1建表2.2 创建存储过程,循环100插入拼接字符串2.3调用存储过程 一: 时间类型TIMESTAMP使用…

process.env 管理 Vue 项目的环境变量(Vue项目中环境变量的配置及调用)

简述:在构建 Vue 应用时,管理配置是开发中的一个重要部分。不同的环境(如开发、测试和生产)往往需要不同的配置,例如 API、 基础 URL、第三方服务的密钥等。使用环境变量可以帮助我们更好地管理这些配置。这里将介绍如…

【Leetcode 566】【Easy】重塑矩阵

目录 题目描述 整体思路 具体代码 题目描述&#xff1a; 原题链接 整体思路 首先要确保重塑后的矩阵内元素个数和原矩阵元素个数要相同&#xff0c;如果不同则原样返回原矩阵。 按行遍历顺序遍历原矩阵&#xff0c;设一个临时vector<int>存放新矩阵的每一行的元素…

数字人大赋能未来治理新篇章,正宇软件助力人大建设新实践

在全面贯彻落实党的二十大精神的开局之年&#xff0c;数字中国战略的深入实施如同一股强劲的东风&#xff0c;吹遍了神州大地的每一个角落。作为数字中国建设的重要组成部分&#xff0c;数字人大作为现代信息技术与人大工作深度融合的产物&#xff0c;正以其独特的魅力和深远的…

Eureka Server集群数据一致性保障策略:深入解析与实践技巧

Eureka Server集群数据一致性保障策略&#xff1a;深入解析与实践技巧 在微服务架构中&#xff0c;服务注册与发现是实现服务间通信的关键机制。Eureka&#xff0c;作为Netflix开源的服务注册与发现框架&#xff0c;其集群模式下的数据一致性问题尤为关键。本文将深入探讨Eure…