【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.pswp.cn/diannao/41175.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41175.shtml
英文地址,請注明出處:http://en.pswp.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 系統中…