日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

测试双打:模拟,假人和存根

發布時間:2023/12/3 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 测试双打:模拟,假人和存根 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大多數班級都有合作者。 在進行單元測試時,您通常希望避免使用那些協作者的實際實現方式來避免測試的脆弱性和綁定/耦合,而應使用測試雙打:模擬,存根和雙打。 本文引用了有關該主題的兩篇現有文章:Martin Fowler的Mocks Are n't Stubs和Bob Uncle的The Little Mocker 。 我都推薦他們。

術語

我將從Gerard Meszaros的書xUnit Test Patterns中借用一個術語。 在其中,他引入了術語“ 被測系統( SUT )”,即我們正在測試的東西。 “測試中的類”是更適用于面向對象的世界的一種替代方法,但是我會堅持使用SUT,因為Fowler也會這樣做。

我還將使用狀態驗證行為驗證這兩個術語。 狀態驗證是通過檢查SUT或其協作者的狀態來驗證代碼是否正常工作。 行為驗證是在驗證協作者是否按照我們期望的方式被調用或調用。

測試雙打

好,回到如何與被測系統的合作者打交道。 對于SUT的每個協作者,您可以使用該協作者的實際實現。 例如,如果您有一個與數據訪問對象(DAO)協作的服務,如下面的WidgetService示例中所示,則可以使用真實的DAO實現。 但是,它很可能與數據庫沖突,這絕對不是我們要進行單元測試所需的數據庫。 另外,如果DAO實現中的代碼發生更改,則可能導致我們的測試開始失敗。 我個人不喜歡當被測代碼本身未更改時測試開始失敗。

因此,我們可以使用有時稱為“測試雙打”的測試。 “測試雙打”一詞也來自Meszaros的xUnit測試模式書。 他將它們描述為“為了明確運行測試而安裝的代替實際組件的任何對象或組件”。

在本文中,我將介紹我使用的三種主要的測試雙打類型:模擬,存根和傻瓜。 我還將簡要介紹兩個我很少明確使用的東西:間諜和假貨。

1.嘲弄

首先,“模擬”是一個過載的術語。 它通常用作任何測試雙精度測試的總稱; 也就是說,任何類型的對象都可以代替測試中的類中的真實協作者。 我對此感到滿意,因為大多數模擬框架都支持此處討論的大多數測試雙打。 但是,出于本文的目的,我將以更嚴格,更有限的含義使用模擬。

具體來說, 模擬是一種使用行為驗證的測試替身類型

馬丁·福勒(Martin Fowler)將模擬描述為“用期望進行預編程的對象,這些對象構成了期望接收的調用的規范”。 正如Bob叔叔所說的那樣,模擬程序會監視正在測試的模塊的行為,并且知道期望的行為。 一個例子可以使它更清楚。

想象一下WidgetService的實現:

public class WidgetService {final WidgetDao dao;public WidgetService(WidgetDao dao) {this.dao = dao;}public void createWidget(Widget widget) {//misc business logic, for example, validating widget is valid//...dao.saveWidget(widget);} }

我們的測試可能看起來像這樣:

public class WidgetServiceTest {//test fixturesWidgetDao widgetDao = mock(WidgetDao.class);WidgetService widgetService = new WidgetService(widgetDao);Widget widget = new Widget();@Testpublic void createWidget_saves_widget() throws Exception {//call method under testwidgetService.createWidget(widget);//verify expectationverify(widgetDao).saveWidget(widget);} }

我們創建了一個WidgetDao的模擬,并驗證它是否如預期的那樣被調用。 我們還可以告訴模擬程序在調用時如何響應。 這是模擬的重要組成部分,允許您操縱模擬,以便可以測試代碼的特定單元,但是在這種情況下,測試不是必需的。

模擬框架

在此示例中,我將Mockito用于模擬框架,但Java空間中還有其他對象,包括EasyMock和JMock 。

自己動手玩?

請注意,您不必使用模擬框架即可使用模擬。 您也可以自己編寫模擬,甚至可以在模擬中構建斷言。 例如,在這種情況下,我們可以創建一個名為WidgetDaoMock的類,該類實現WidgetDao接口,并且該類的createWidget()方法的實現僅記錄其被調用的情況。 然后,您可以驗證呼叫是否按預期進行。 盡管如此,現代的模擬框架仍然使這種“勞碌自在”的解決方案變得多余。

2.存根

存根是為了測試目的而“存根”或提供實現的大大簡化版本的對象。

例如,如果我們的WidgetService類現在也也依賴于ManagerService。 請參閱此處的標準化方法:

public class WidgetService {final WidgetDao dao;final ManagerService manager;public WidgetService(WidgetDao dao, ManagerService manager) {this.dao = dao;this.manager = manager;}public void standardize(Widget widget) {if (manager.isActive()) {widget.setStandardized(true);}}public void createWidget(Widget widget) {//omitted for brevity} }

并且我們想測試當管理器處于活動狀態時,標準化方法是否“標準化”了一個小部件,我們可以使用如下所示的存根:

public class WidgetServiceTest {WidgetDao widgetDao = mock(WidgetDao.class);Widget widget = new Widget();class ManagerServiceStub extends ManagerService {@Overridepublic boolean isActive() {return true;}}@Testpublic void standardize_standardizes_widget_when_active() {//setupManagerServiceStub managerServiceStub = new ManagerServiceStub();WidgetService widgetService = new WidgetService(widgetDao, managerServiceStub);//call method under testwidgetService.standardize(widget);//verify stateassertTrue(widget.isStandardized());} }

由于模擬通常用于行為驗證,而存根可用于狀態驗證或行為驗證。

該示例非常基礎,也可以使用模擬來完成,但是存根可以為測試夾具的可配置性提供一種有用的方法。 我們可以對ManagerServiceStub進行參數化,以使其將“活動”字段的值用作構造函數參數,因此可以在否定測試用例中重用。 也可以使用更復雜的參數和行為。 其他選項包括將存根創建為匿名內部類,或為存根創建基類,例如ManagerServiceStubBase,以供其他人擴展。 后者的優點是,如果ManagerService接口發生更改,則只有ManagerServiceStubBase類會中斷,并且需要更新。

我傾向于經常使用存根。 我喜歡他們提供的靈活性,以便能夠自定義測試裝置,并提供純Java代碼提供的清晰度。 將來的維護者不需要能夠理解某個框架。 我的大多數同事似乎更喜歡使用模擬框架。 找到最適合您的方法,并運用最佳判斷。

3.假人

顧名思義,虛擬對象是非常愚蠢的類。 它幾乎不包含任何內容,基本上只足以使您的代碼得以編譯。 當您不在乎如何使用虛擬對象時,可以將其傳遞給某些對象。 例如,作為測試的一部分,當您必須傳遞參數時,但是您不希望使用該參數。

例如,在前面的示例中的standardize_standardizes_widget_when_active()測試中,我們仍然繼續使用模擬的WidgetDao。 虛擬對象可能是一個更好的選擇,因為我們根本不希望在createWidget()方法中完全使用WidgetDao。

public class WidgetServiceTest {Widget widget = new Widget();class ManagerServiceStub extends ManagerService {@Overridepublic boolean isActive() {return true;}}class WidgetDaoDummy implements WidgetDao {@Overridepublic Widget getWidget() {throw new RuntimeException("Not expected to be called");}@Overridepublic void saveWidget(Widget widget) {throw new RuntimeException("Not expected to be called");}}@Testpublic void standardize_standardizes_widget_when_active() {//setupManagerServiceStub managerServiceStub = new ManagerServiceStub();WidgetDaoDummy widgetDao = new WidgetDaoDummy();WidgetService widgetService = new WidgetService(widgetDao, managerServiceStub);//call method under testwidgetService.standardize(widget);//verify stateassertTrue(widget.isStandardized());} }

在這種情況下,我創建了一個內部類。 在大多數情況下,由于Dummy功能很少會在測試之間發生變化,因此創建非內部類并為所有測試重用更為有意義。

還要注意在這種情況下,使用模擬框架創建類的模擬實例也是可行的選擇。 我個人很少使用假人,而是創建這樣的模擬:

WidgetDaoDummy widgetDao = mock(WidgetDao.class);

盡管可以肯定的是,當確實發生意外調用時,拋出異常會更加困難(這取決于您選擇的模擬框架),但是它確實具有簡潔性的巨大優勢。 虛擬變量可能很長,因為它們需要在接口中實現每種方法。

與存根一樣,假人可用于狀態或行為驗證。

間諜與偽造

我將簡要介紹另外兩種測試雙打:間諜和偽造。 我之所以簡短地說,是因為我個人很少自己明確使用這兩種類型的雙打,而且還因為術語可能會引起混亂,而又不會引起更多細微差別! 但是為了完整性……

間諜

當您想確保系統調用了某個方法時,可以使用間諜程序。 它還可以記錄各種事情,例如計算調用次數,或記錄每次傳遞的參數。

但是,對于間諜來說,存在將測試與代碼實現緊密耦合的危險。

間諜專用于行為驗證。

大多數現代的模擬框架也很好地涵蓋了這種功能。

假貨

馬丁·福勒(Martin Fowler)對偽造品的描述如下:偽造品具有有效的實現方式,但通常采取一些捷徑,這使其不適合生產(內存數據庫是一個很好的例子)。

我個人很少使用它們。

結論

測試雙打是單元測試不可或缺的一部分。 嘲笑,存根和雙打都是有用的工具,了解它們之間的差異很重要。

從最嚴格的意義上講,模擬只是使用行為驗證的雙精度形式。 指定了兩倍的期望值,然后在調用SUT時進行驗證。 但是,工作模擬也已經變得越來越籠統地描述了此處描述的任何雙打,實際上大多數現代模擬框架都可以這種通用方式使用。

最后,您應該使用哪種雙精度型? 這取決于所測試的代碼,但是我建議您遵循使您的測試意圖最清楚的任何方式進行指導。

資料來源

  • 莫蒂不是存根作者 ,馬丁·福勒(Martin Fowler)
  • 小嘲笑 ,“叔叔”鮑勃·馬丁
  • xUnit測試模式 ,作者Gerard Meszaros

翻譯自: https://www.javacodegeeks.com/2015/11/test-doubles-mocks-dummies-and-stubs.html

總結

以上是生活随笔為你收集整理的测试双打:模拟,假人和存根的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 性午夜| 国产精品丝袜在线 | 色眯眯视频 | 性生活视频在线播放 | 日韩在线免费播放 | 一级黄色免费 | 欧美激情国产一区 | 久久人人妻人人人人妻性色av | 成人性生交大片免费看中文 | 高清av网站| 色香蕉网站 | 日本电影成人 | 中文成人在线 | 久久中文字幕人妻熟av女蜜柚m | 影音av资源 | 小日子的在线观看免费第8集 | 免费色网址| 成人免费视频大全 | 韩日精品在线 | 办公室大战高跟丝袜秘书经理ol | 欧美另类一区二区 | 色网站在线免费观看 | 国产一级黄色片子 | 亚洲一二三不卡 | 牛夜精品久久久久久久99黑人 | 亚洲精品一线 | 久久久96人妻无码精品 | 国产精品一区二区电影 | 国产亚洲一区二区三区在线观看 | 欧美一区二区三区视频 | 97精品国产 | 亚洲欧洲日产av | 国产免费自拍视频 | 久久久久久视 | 亚洲av成人精品毛片 | 亚洲色图 一区二区 | 人与动物毛片 | 艹男人的日日夜夜 | 国产精品一区二区在线播放 | 成人动态视频 | 六月丁香啪啪 | 日本电影一区 | www狠狠 | 亚洲伦理精品 | 国产精品一区久久久 | 一级黄色片国产 | 成人国产精品免费观看视频 | 国产女主播av | 国产午夜无码视频在线观看 | 久久五月视频 | 日本韩国中文字幕 | 午夜爽视频 | 99热只有 | 国内外成人激情视频 | av免费网站在线观看 | 精品国产一区二区三区无码 | 波多野结衣国产 | 在线观看亚洲专区 | 国产黄色小说 | 人人妻人人澡人人爽精品日本 | 欧美xxxx中国 | 在线观看日批 | 农村妇女av | 国产又粗又猛又黄视频 | 花房姑娘免费全集 | www,色| 国产福利专区 | 日韩中文字幕视频在线观看 | 亚洲a在线观看 | 亚洲精品综合精品自拍 | 国产黄色高清视频 | 97自拍网 | 亚洲网在线| 成人性生交大片免费看中文 | 色导航| 香蕉av一区二区 | 国产精品久久久久影院 | 国产精品免费无遮挡无码永久视频 | 中日韩在线播放 | 国产又大又硬又粗 | 黄色污污视频网站 | 娇妻被老王脔到高潮失禁视频 | 女同av在线播放 | 日韩福利视频网 | 激情网综合 | 日本少妇三级 | 五号特工组之偷天换月 | 亚洲免费精品视频 | av中字 | 国产真实乱偷精品视频 | 色天天综合 | 五月激情久久 | 国产一线av| 中文字幕一区二区三区乱码人妻 | 国产一级片a | 久久久久亚洲精品国产 | 韩国日本在线观看 | 黄色伊人网 | 性感美女一区 |