存根类 测试代码 java_嘲弄和存根–了解Mockito的测试双打
存根類 測試代碼 java
介紹 我遇到的一件事是使用模擬框架的團隊假設他們在模擬。
他們并不知道Mocks只是Gerard Meszaros在xunitpatterns.com上分類的“測試雙打”之一。
重要的是要認識到每種類型的雙重測試在測試中扮演著不同的角色。 用與學習不同模式或重構相同的方式,您需要了解每種類型的測試double的原始角色。 然后可以將它們組合起來以滿足您的測試需求。
我將簡要介紹這種分類的產生方式以及每種類型的不同之處。
我將在Mockito中使用一些簡短的簡單示例進行此操作。
一段簡短的歷史
多年來,人們一直在編寫系統組件的輕量級版本以幫助進行測試。 通常,這被稱為存根。 在2000年的文章“ Endo-Testing:使用模擬對象進行單元測試”中介紹了模擬對象的概念。 從那時起,Meszaros將Stub,Mocks和許多其他類型的測試對象歸類為Double Double。
該術語已由Martin Fowler在“ Mocks Are n't Stubs”中引用,并在Microsoft社區中被采用,如“ Exploring The Test Doubles Continuum of Test Doubles”中所示。
參考部分中顯示了這些重要論文的鏈接。
考試雙打的類別
上圖顯示了常用的雙重測試類型。 以下URL提供了對每個模式及其功能以及替代術語的很好的交叉引用。
http://xunitpatterns.com/Test%20Double.html
莫基托
Mockito是一個測試間諜框架,學習起來非常簡單。 Mockito值得注意的是,在測試之前沒有定義任何模擬對象的期望,因為它們有時在其他模擬框架中也是如此。 開始嘲笑時,這會導致更自然的樣式(IMHO)。
以下示例在這里純粹是為了簡單演示如何使用Mockito實施不同類型的測試雙打。
網站上有大量有關如何使用Mockito的特定示例。
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html
使用Mockito測試雙打
以下是一些使用Mockito的基本示例,以顯示Meszaros定義的每個測試雙打的作用。
我為每個對象都提供了指向主要定義的鏈接,因此您可以獲得更多示例和完整定義。
虛擬對象
http://xunitpatterns.com/Dummy%20Object.html
這是所有測試雙打中最簡單的一次。 這是一個沒有實現的對象,僅用于填充與測試無關的方法調用的參數。
例如,下面的代碼使用大量代碼來創建客戶,這對測試并不重要。
只要客戶數恢復為1,該測試就不會在乎添加哪個客戶。
我們實際上并不關心客戶對象的內容,但是它是必需的。 我們可以嘗試使用null值,但是如果代碼正確,則可能會引發某種異常。
@Test(expected=Exception.class) public void addNullCustomerTest() {Customer dummy = null;AddressBook addressBook = new AddressBook();addressBook.addCustomer(dummy); }為了避免這種情況,我們可以使用一個簡單的Mockito假人來獲得所需的行為。
@Test public void addCustomerWithDummyTest() {Customer dummy = mock(Customer.class);AddressBook addressBook = new AddressBook();addressBook.addCustomer(dummy);Assert.assertEquals(1, addressBook.getNumberOfCustomers()); }正是這個簡單的代碼創建了一個要傳遞給調用的虛擬對象。
Customer dummy = mock(Customer.class); 不要被模擬語法所迷惑-這里扮演的角色是虛擬的,而不是模擬的。
區別在于測試雙重性的作用,而不是用于創建雙重性的語法。
該類可以輕松替代客戶類,并使測試非常容易閱讀。
測試存根
http://xunitpatterns.com/Test%20Stub.html
測試存根的作用是將受控值返回到要測試的對象。 這些被描述為測試的間接輸入。 希望有一個例子可以闡明這意味著什么。
采取以下代碼
public class SimplePricingService implements PricingService { PricingRepository repository;public SimplePricingService(PricingRepository pricingRepository) {this.repository = pricingRepository;}@Overridepublic Price priceTrade(Trade trade) {return repository.getPriceForTrade(trade);}@Overridepublic Price getTotalPriceForTrades(Collectiontrades) {Price totalPrice = new Price();for (Trade trade : trades){Price tradePrice = repository.getPriceForTrade(trade);totalPrice = totalPrice.add(tradePrice);}return totalPrice;} SimplePricingService具有一個協作對象,即交易存儲庫。 交易存儲庫通過getPriceForTrade方法將交易價格提供給定價服務。
為了測試SimplePricingService中的業務邏輯,我們需要控制這些間接輸入
即我們從未通過測試的輸入。 如下所示。
在下面的示例中,我們對PricingRepository存根以返回可用于測試SimpleTradeService的業務邏輯的已知值。
@Test public void testGetHighestPricedTrade() throws Exception {Price price1 = new Price(10); Price price2 = new Price(15);Price price3 = new Price(25);PricingRepository pricingRepository = mock(PricingRepository.class);when(pricingRepository.getPriceForTrade(any(Trade.class))).thenReturn(price1, price2, price3);PricingService service = new SimplePricingService(pricingRepository);Price highestPrice = service.getHighestPricedTrade(getTrades());assertEquals(price3.getAmount(), highestPrice.getAmount()); }破壞者的例子
測試存根有2個常見的變體:響應者和破壞者。
如前面的示例,使用響應者來測試快樂路徑。
破壞者用于測試以下異常行為。
模擬對象
http://xunitpatterns.com/Mock%20Object.html
模擬對象用于在測試期間驗證對象行為。 通過對象行為,我的意思是我們檢查在運行測試時是否在對象上執行了正確的方法和路徑。
這與存根的支持作用完全不同,存根用于為您正在測試的任何結果提供結果。 在存根中,我們使用為方法定義返回值的模式。
在模擬中,我們使用以下形式檢查對象的行為。
verify(listMock).add(s); 這是一個簡單的示例,我們要測試是否正確審核了新交易。
這是主要代碼。
下面的測試為貿易存儲庫創建存根,并為AuditService創建模擬
然后,我們在模擬的AuditService上調用verify,以確保TradeService調用了
logNewTrade方法正確
以下行對模擬的AuditService進行檢查。
verify(auditService).logNewTrade(trade);該測試使我們能夠證明審計服務在創建交易時的行為正確。
測試間諜
http://xunitpatterns.com/Test%20Spy.html
值得一看上面的鏈接,以嚴格定義測試間諜。
但是在Mockito中,我喜歡使用它來包裝實際對象,然后驗證或修改它的行為以支持您的測試。 這是我們檢查列表的標準行為的示例。 注意,我們既可以驗證是否調用了add方法,也可以斷言該項目已添加到列表中。
將其與僅可驗證方法調用的模擬對象進行比較。 因為我們僅模擬列表的行為,所以它不記錄已添加項目,并且在調用size()方法時返回默認值零。
@Mock ListlistMock = new ArrayList();@Test public void testMockReturnsZero() throws Exception {String s = 'dobie';listMock.add(new String(s));verify(listMock).add(s);assertEquals(0, listMock.size()); } testSpy的另一個有用功能是能夠對返回調用進行存根。 完成此操作后,該對象將表現正常,直到調用存根方法為止。
在此示例中,我們將get方法存根以始終引發RuntimeException。 其余行為保持不變。
在此示例中,我們再次保留了核心行為,但更改了size()方法以初始返回1,并為所有后續調用返回5。
public void testSpyReturnsStubbedValues2() throws Exception {int size = 5;when(listSpy.size()).thenReturn(1, size);int mockedListSize = listSpy.size();assertEquals(1, mockedListSize);mockedListSize = listSpy.size();assertEquals(5, mockedListSize); mockedListSize = listSpy.size();assertEquals(5, mockedListSize); }這真是不可思議!
假物件
http://xunitpatterns.com/Fake%20Object.html
假物品通常是手工制作或重量較輕的物品,僅用于測試,不適合生產。 一個很好的例子是內存數據庫或偽造的服務層。
它們往往提供比標準測試雙打更多的功能,因此通常不適合使用Mockito進行實現。 這并不是說它們不能像這樣構造,只是可能不值得采用這種方式來實現。
參考:“ 小事半解 ” – 敏捷工程技術博客上來自JCG合作伙伴 John Dobie的Mockito了解測試雙打 。
翻譯自: https://www.javacodegeeks.com/2012/05/mocks-and-stubs-understanding-test.html
存根類 測試代碼 java
總結
以上是生活随笔為你收集整理的存根类 测试代码 java_嘲弄和存根–了解Mockito的测试双打的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红帽JBoss企业应用平台7.0 ALP
- 下一篇: linux脚本if的判断条件(linux