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

文章目录

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

问题描述

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

	@Testpublic void updateNumAsync() {Integer newNum = 600;// updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据// 生成要用的stubwhen(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结束的太早,那么强行让他多等一会是不是就好了?

	@Testpublic void updateNumAsync() throws InterruptedException {Integer newNum = 600;// updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据// 生成要用的stubwhen(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 调用之前被回收。

	@Testpublic void updateNumAsync() throws  InterruptedException, ExecutionException {Integer newNum = 600;// updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据// 生成要用的stubwhen(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()
这个方法在前面那个问题里也是能让测试通过的。

	@Testpublic void updateNumAsync(){Integer newNum = 600;// updateRoleCountAsync用CompletableFuture异步调用的ApiUtil.put发送http请求更新对方服务端的数据// 生成要用的stubMockito.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.mzph.cn/diannao/41175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins 强制杀job

有时候有的jenkins job运行时间太长,在jenkins界面点击x按钮进行abort,会失败: 这时候点击: “Click here to forcibly terminate running steps” 会进一步kill 任务,但是也还是有杀不掉的可能性。 终极武器是jenkin…

vue3【提效】使用 VueUse 高效开发(工具库 @vueuse/core + 新增的组件库 @vueuse/components)

Vueuse 是一个功能强大的 Vue.js 生态系统工具库,提供了可重用的组件和函数,帮助开发者更轻松地构建复杂的应用程序。 官网 :https://vueuse.org/core/useWindowScroll/ 安装 VueUse npm i vueuse/core vueuse/components(可选&a…

llm学习-4(llm和langchain)

langchain说明文档:langchain 0.2.6 — 🦜🔗 langChain 0.2.6https://api.python.langchain.com/en/latest/langchain_api_reference.html#module-langchain.chat_models 1:模型 (1)自定义模型导入&#x…

跟《经济学人》学英文:2024年07月06日这期 Amazon turns 30

As Amazon turns 30, three factors will define its next decade It will have to deal with trustbusters, catch up on AI and revive its core business 它将不得不应对反垄断者,追赶人工智能并重振其核心业务 trustbuster: 美 [ˈtrəs(t)ˌbəs…

Java中的算法优化与复杂度分析

Java中的算法优化与复杂度分析 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在软件开发中,算法的效率直接影响到程序的性能和响应速度。算法优化…

你真的会ELISA加样吗?

在ELISA实验中,研究人员需要进行多次加样步骤完成实验操作。对于常规双抗体夹心法ELISA,一般有如下加样步聚,即加样本、加检测抗体、加酶结合物、加底物(最后加终止液停止反应)。 加样步骤基础知识 加样步骤中一般使用…

云仓酒庄北京公司2024年:深耕酒业生态,以专业筑基

云仓酒庄北京公司:深耕酒业生态,以专业筑基,共绘酒业新蓝图 在竞争日益激烈的酒类市场中,云仓酒庄北京公司以其稳健的步伐、专业底蕴以及对品质的不懈追求,正逐步成为行业内一股不可忽视的力量。这家公司不仅仅是一个…

高级java每日一道面试题-2024年7月5日

题目: 请描述 Java 中接口和抽象类的区别,并说明什么时候应该使用接口,什么时候应该使用抽象类。 解答: 接口和抽象类都是 Java 中用于实现面向对象编程的重要概念,但它们在功能和用法上有一些区别: 1.…

把Windows打造成一个NTP网络时间服务器,为网关提供校时服务

把Windows打造成一个NTP网络时间服务器,为网关提供校时服务。主要目的是为了解决:当网关不能上外网的时候,可以使用局域网的电脑来当做NTP服务器,实现校时功能。 跟着小编来看,如何使用NTP网络时间服务器来同步时间。 …

Laravel为什么会成为最优雅的PHP框架?

引言 在现代Web开发中,选择一个合适的框架是构建高效、可靠和可维护应用的关键。从简单的博客到复杂的企业级应用,PHP框架一直在不断演变和进步。其中,Laravel作为一个相对较新的框架,自2011年首次发布以来,迅速崛起并…

ubuntu关于docker部署 项目一站式教程

**假设已有ubuntu服务器并且登录root账号 ** **FinalShell中复制快捷键是 ****Ctrl+Shift+V** 卸载老版本docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker步骤 更新软件包sudo apt update sudo apt upgrade安装docker依赖sudo apt-get …

监控工具 Prometheus

监控工具 Prometheus Prometheus 是一个开源的监控解决方案,它能够收集、存储和查询指标数据,并提供了强大的报警和可视化功能。Prometheus 适用于监控云原生应用程序和基础设施,是 Kubernetes 生态系统中常用的监控工具之一。 1. Promethe…

Yarn有哪些功能特点

Yarn是一个由Facebook团队开发,并联合Google、Exponent和Tilde等公司推出的JavaScript包管理工具,旨在提供更优的包管理体验,解决npm(Node Package Manager)的一些痛点。Yarn的功能特点主要包括以下几个方面&#xff1…

分享 10个简单实用的 JS 代码技巧

代码图片生成工具:有码高清 一、滚动到页面顶部 我们可以使用 window.scrollTo() 平滑滚动到页面顶部。 源码: const scrollToTop () > {window.scrollTo({ top: 0, left: 0, behavior: "smooth" }); };二、滚动到页面底部 当然&…

汉王、绘王签字版调用封装

说明 需要配合汉王或绘王签字版驱动以及对应的sdk服务使用 constants.js //汉王、绘王sdk websocket连接地址 export const WS_URLS {1:ws://127.0.0.1:29999, //汉王2:ws://127.0.0.1:7181, }export const COMMAND1 {1: {HWPenSign: "HWStartSign",nLogo: "…

探索大型语言模型自动评估 LLM 输出长句准确性的方法

LLM现在能够自动评估较长文本中的事实真实性 源码地址:https://github.com/google-deepmind/long-form-factuality 论文地址:https://arxiv.org/pdf/2403.18802.pdf 这篇论文是关于谷歌DeepMind的,提出了新的数据集、评估方法和衡量标准&am…

vue2+element-ui新增编辑表格+删除行

实现效果&#xff1a; 代码实现 &#xff1a; <el-table :data"dataForm.updateData"border:header-cell-style"{text-align:center}":cell-style"{text-align:center}"><el-table-column label"选项字段"align"center&…

Linux 内核 GPIO 用户空间接口

文章目录 Linux 内核 GPIO 接口旧版本方式&#xff1a;sysfs 接口新版本方式&#xff1a;chardev 接口 gpiod 库及其命令行gpiod 库的命令行gpiod 库函数的应用 GPIO&#xff08;General Purpose Input/Output&#xff0c;通用输入/输出接口&#xff09;&#xff0c;是微控制器…

MAX()和ROW_NUMBER()函数的对比

SQL 查询中,使用 MAX() 函数和使用窗口函数 ROW_NUMBER() 都可以实现获取每个分组中某个列的最大值,但它们的实现方式和性能表现有所不同。以下是两者的区别和性能对比: 使用 MAX() 函数 SELECTMAX(d.times) FROMv_y d WHEREd.id = a.idAND d.name = a.nameAND d.age = a.…

交换机需要多大 buffer(续:更一般的原理)

前面用 aimd 系统分析了交换机 buffer 需求量随流数量增加而减少&#xff0c;今天从更一般的角度继续分析这事。 将交换机建模为一个 m/m/1 排队系统&#xff0c;多流场景下它就会变成一个 m/g/1 排队系统&#xff0c;而这事比前面的 aimd 系统分析更容易推导。 m/m/1 系统中…