成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

測(cè)試中 Fakes、Mocks 以及 Stubs 概念明晰

開發(fā) 開發(fā)工具
在 securityOn 方法執(zhí)行之后,window 與 door 的 Mock 對(duì)象已經(jīng)記錄了所有的交互信息,這就允許我們能夠去驗(yàn)證 Window 與 Door 是否被真實(shí)的調(diào)用。

自動(dòng)化測(cè)試中,我們常會(huì)使用一些經(jīng)過(guò)簡(jiǎn)化的,行為與表現(xiàn)類似于生產(chǎn)環(huán)境下的對(duì)象的復(fù)制品。引入這樣的復(fù)制品能夠降低構(gòu)建測(cè)試用例的復(fù)雜度,允許我們獨(dú)立而解耦地測(cè)試某個(gè)模塊,不再擔(dān)心受到系統(tǒng)中其他部分的影響;這類型對(duì)象也就是所謂的 Test Double。實(shí)際上對(duì)于 Test Double 的定義與闡述也是見仁見智,Gerard Meszaros 在這篇文章中就介紹了五個(gè)不同的 Double 類型;而人們更傾向于使用 Mock 來(lái)統(tǒng)一描述不同的 Test Doubles。不過(guò)對(duì)于 Test Doubles 實(shí)現(xiàn)的誤解還是可能會(huì)影響到測(cè)試的設(shè)計(jì),使測(cè)試用例變得混亂和脆弱,最終帶來(lái)不必要的重構(gòu)。本文則是從作者個(gè)人的角度描述了常見的 Test Doubles 類型及其具體的實(shí)現(xiàn):Fake、Stub 與 Mock,并且給出了不同的 Double 的使用場(chǎng)景。

[[191910]]

Fake

  • Fakes are objects that have working implementations, but not same as production one. Usually they take some shortcut and have simplified version of production code.Fake 是那些包含了生產(chǎn)環(huán)境下具體實(shí)現(xiàn)的簡(jiǎn)化版本的對(duì)象。

如下圖所示,F(xiàn)ake 可以是某個(gè) Data Access Object 或者 Repository 的基于內(nèi)存的實(shí)現(xiàn);該實(shí)現(xiàn)并不會(huì)真的去進(jìn)行數(shù)據(jù)庫(kù)操作,而是使用簡(jiǎn)單的 HashMap 來(lái)存放數(shù)據(jù)。這就允許了我們能夠在并沒(méi)有真的啟動(dòng)數(shù)據(jù)庫(kù)或者執(zhí)行耗時(shí)的外部請(qǐng)求的情況下進(jìn)行服務(wù)的測(cè)試。

  1. @Profile("transient"
  2. public class FakeAccountRepository implements AccountRepository { 
  3.  
  4.    Map<User, Account> accounts = new HashMap<>(); 
  5.  
  6.    public FakeAccountRepository() { 
  7.        this.accounts.put(new User("john@bmail.com"), new UserAccount()); 
  8.        this.accounts.put(new User("boby@bmail.com"), new AdminAccount()); 
  9.    } 
  10.  
  11.    String getPasswordHash(User user) { 
  12.        return accounts.get(user).getPasswordHash(); 
  13.    } 

除了應(yīng)用到測(cè)試,F(xiàn)ake 還能夠用于進(jìn)行原型設(shè)計(jì)或者峰值模擬中;我們能夠迅速地實(shí)現(xiàn)系統(tǒng)原型,并且基于內(nèi)存存儲(chǔ)來(lái)運(yùn)行整個(gè)系統(tǒng),推遲有關(guān)數(shù)據(jù)庫(kù)設(shè)計(jì)所用到的一些決定。另一個(gè)常見的使用場(chǎng)景就是利用 Fake 來(lái)保證在測(cè)試環(huán)境下支付永遠(yuǎn)返回成功結(jié)果。

Stub

  • Stub is an object that holds predefined data and uses it to answer calls during tests. It is used when we cannot or don’t want to involve objects that would answer with real data or have undesirable side effects.Stub 代指那些包含了預(yù)定義好的數(shù)據(jù)并且在測(cè)試時(shí)返回給調(diào)用者的對(duì)象。Stub 常被用于我們不希望返回真實(shí)數(shù)據(jù)或者造成其他副作用的場(chǎng)景。

Stub 的典型應(yīng)用場(chǎng)景即是當(dāng)某個(gè)對(duì)象需要從數(shù)據(jù)庫(kù)抓取數(shù)據(jù)時(shí),我們并不需要真實(shí)地與數(shù)據(jù)庫(kù)進(jìn)行交互或者像 Fake 那樣從內(nèi)存中抓取數(shù)據(jù),而是直接返回預(yù)定義好的數(shù)據(jù)。

  1. public class GradesService { 
  2.  
  3.    private final Gradebook gradebook; 
  4.  
  5.    public GradesService(Gradebook gradebook) { 
  6.        this.gradebook = gradebook; 
  7.    } 
  8.  
  9.    Double averageGrades(Student student) { 
  10.        return average(gradebook.gradesFor(student)); 
  11.    } 

我們?cè)诰帉憸y(cè)試用例時(shí)并沒(méi)有從 Gradebook 存儲(chǔ)中抓取數(shù)據(jù),而是在 Stub 中直接定義好需要返回的成績(jī)列表;我們只需要足夠的數(shù)據(jù)來(lái)保證對(duì)平均值計(jì)算函數(shù)進(jìn)行測(cè)試就好了。

  1. public class GradesServiceTest { 
  2.  
  3.    private Student student; 
  4.    private Gradebook gradebook; 
  5.  
  6.    @Before 
  7.    public void setUp() throws Exception { 
  8.        gradebook = mock(Gradebook.class); 
  9.        student = new Student(); 
  10.    } 
  11.  
  12.    @Test 
  13.    public void calculates_grades_average_for_student() { 
  14.        when(gradebook.gradesFor(student)).thenReturn(grades(8, 6, 10)); //stubbing gradebook 
  15.  
  16.        double averageGrades = new GradesService(gradebook).averageGrades(student); 
  17.  
  18.        assertThat(averageGrades).isEqualTo(8.0); 
  19.    } 

Command Query Separation

僅返回部分結(jié)果而并沒(méi)有真實(shí)改變系統(tǒng)狀態(tài)的的方法被稱作查詢(Query)。譬如 avarangeGrades,用于返回學(xué)生成績(jī)平均值的函數(shù)就是非常典型的例子:Double getAverageGrades(Student student);。該函數(shù)僅返回了某個(gè)值,而沒(méi)有其他的任何副作用。正如我們上文中介紹的,我們可以使用 Stubs 來(lái)替換提供實(shí)際成績(jī)值的函數(shù),從而簡(jiǎn)化了整個(gè)測(cè)試用例的編寫。不過(guò)除了 Query 之外還有另一個(gè)類別的方法,被稱作 Command。即當(dāng)某個(gè)函數(shù)在執(zhí)行某些操作的時(shí)候還改變了系統(tǒng)狀態(tài),不過(guò)該類型函數(shù)往往沒(méi)有什么返回值:void sendReminderEmail(Student student);。這種對(duì)于方法的劃分方式也就是 Bertrand Meyer 在Object Oriented Software Construction 一書中介紹的 Command Query 分割法。

對(duì)于 Query 類型的方法我們會(huì)優(yōu)先考慮使用 Stub 來(lái)代替方法的返回值,而對(duì)于 Command 類型的方法的測(cè)試則需要依賴于 Mock。

Mock

  • Mocks are objects that register calls they receive. In test assertion we can verify on Mocks that all expected actions were performed.Mocks 代指那些僅記錄它們的調(diào)用信息的對(duì)象,在測(cè)試斷言中我們需要驗(yàn)證 Mocks 被進(jìn)行了符合期望的調(diào)用。

當(dāng)我們并不希望真的調(diào)用生產(chǎn)環(huán)境下的代碼或者在測(cè)試中難于驗(yàn)證真實(shí)代碼執(zhí)行效果的時(shí)候,我們會(huì)用 Mock 來(lái)替代那些真實(shí)的對(duì)象。典型的例子即是對(duì)郵件發(fā)送服務(wù)的測(cè)試,我們并不希望每次進(jìn)行測(cè)試的時(shí)候都發(fā)送一封郵件,畢竟我們很難去驗(yàn)證郵件是否真的被發(fā)出了或者被接收了。我們更多地關(guān)注于郵件服務(wù)是否按照我們的預(yù)期在合適的業(yè)務(wù)流中被調(diào)用,其概念如下圖所示: 

  1. public class SecurityCentral { 
  2.  
  3.    private final Window window; 
  4.    private final Door door; 
  5.  
  6.    public SecurityCentral(Window window, Door door) { 
  7.        this.window = window; 
  8.        this.door = door; 
  9.    } 
  10.  
  11.    void securityOn() { 
  12.        window.close(); 
  13.        door.close(); 
  14.    } 

在上述代碼中,我們并不想真的去關(guān)門來(lái)測(cè)試 securityOn 方法,因此我們可以設(shè)置合適的 Mock 對(duì)象:

  1. public class SecurityCentralTest { 
  2.  
  3.    Window windowMock = mock(Window.class); 
  4.    Door doorMock = mock(Door.class); 
  5.  
  6.    @Test 
  7.    public void enabling_security_locks_windows_and_doors() { 
  8.        SecurityCentral securityCentral = new SecurityCentral(windowMock, doorMock); 
  9.  
  10.        securityCentral.securityOn(); 
  11.  
  12.        verify(doorMock).close(); 
  13.        verify(windowMock).close(); 
  14.    } 

在 securityOn 方法執(zhí)行之后,window 與 door 的 Mock 對(duì)象已經(jīng)記錄了所有的交互信息,這就允許我們能夠去驗(yàn)證 Window 與 Door 是否被真實(shí)的調(diào)用。或許有人會(huì)疑問(wèn)是否在真實(shí)環(huán)境下門與窗是否被真的關(guān)閉了?其實(shí)我們并不能保證,不過(guò)這也不是我們關(guān)注的點(diǎn),也不是 SecurityCentral 這個(gè)類關(guān)注的目標(biāo)。門與窗是否能被正常的關(guān)閉應(yīng)該是由 Door 與 Window 這兩個(gè)類所關(guān)注的。

【本文是51CTO專欄作者“張梓雄 ”的原創(chuàng)文章,如需轉(zhuǎn)載請(qǐng)通過(guò)51CTO與作者聯(lián)系】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來(lái)源: 51CTO專欄
相關(guān)推薦

2009-07-09 17:09:49

MyEclipse

2010-01-19 17:23:11

TongWeb

2009-08-28 13:12:56

C#反射實(shí)例C#反射

2019-04-17 15:35:37

Redis數(shù)據(jù)庫(kù)數(shù)據(jù)結(jié)構(gòu)

2009-09-09 10:47:29

C# CheckBox

2012-05-29 09:42:08

Linux服務(wù)器窗口管理

2010-09-14 10:16:55

服務(wù)器虛擬化

2010-08-14 21:59:35

2020-12-08 12:24:55

接口測(cè)試Interface

2009-10-12 17:02:13

2017-04-28 14:25:06

支付卡合規(guī)方案

2009-09-04 17:53:51

C# Main函數(shù)

2009-12-25 15:36:29

雙線路接入技術(shù)

2012-03-12 09:39:38

大數(shù)據(jù)IT資源

2021-08-06 06:38:49

安卓應(yīng)用Android 性能測(cè)試

2009-09-11 03:21:00

網(wǎng)絡(luò)故障診斷

2011-05-20 17:59:06

回調(diào)函數(shù)

2009-11-24 10:06:21

SUSE enterp

2013-07-29 10:27:19

2014-04-11 13:41:34

即刻搜索即刻合并
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩欧美一区二区三区免费观看 | 91精品国产91 | 亚洲综合视频 | 可以在线看的黄色网址 | 红色av社区 | 欧美爱爱视频网站 | 玖玖爱365| 欧美嘿咻| 中文在线一区二区 | 欧美精品一区二区三区四区 在线 | 亚洲国产aⅴ成人精品无吗 亚洲精品久久久一区二区三区 | 在线免费看黄 | 日韩中文一区 | 国产精品揄拍一区二区 | 中文字幕av亚洲精品一部二部 | 午夜在线影院 | 国产精品久久国产精品 | 免费成人高清在线视频 | 亚洲综合国产 | 亚洲国产视频一区二区 | 在线看无码的免费网站 | 国产麻豆乱码精品一区二区三区 | 欧美日韩国产一区 | 午夜影院在线观看 | 精品久久久久久久久亚洲 | 国产成都精品91一区二区三 | 激情网五月天 | 狠狠干av | 日日摸夜夜添夜夜添精品视频 | av免费观看在线 | 国产在线观看 | 国产偷录叫床高潮录音 | 久国久产久精永久网页 | 无吗视频| 免费国产一区 | 成人黄色av| 欧美日韩在线一区二区三区 | 成年人黄色一级毛片 | 91亚洲一区| av免费网站在线观看 | 国产91视频免费 |