使用模拟进行测试
如果使用正確的方法,模擬對象將非常有用。 我在需要驅動軟件開發使用的帖子中分享了一些使用Mock Objects的經驗。
在這篇文章中,我分享了兩件事
–使用模擬進行基于合同的測試。
–用于組織模擬代碼的模式。
基于合同的測試
讓我們以正在構建匯款服務的場景為例。 這種服務類型的關鍵組件是貨幣轉換器,銀行服務和外匯服務。
50000英尺的虛擬外匯服務設計如下所示。
我們必須編寫需要貨幣換算和銀行轉賬服務的外匯服務。
這是基于接觸的測試的理想方案。
FXService的代碼段
public class FXService {private final CurrencyConverter currencyConverter;private final BankService bankService;private final double commissionPer;public String transfer(Money money, BankAccount destinationAccount, Currency target) {String sourceCurrency = money.currency().name();String targetCurrency = target.name();double commissionAmount = calculateCommission(money.amount());double fxRate = currencyConverter.convert(1, sourceCurrency, targetCurrency); // First interaction double transferAmount = calculateTransferAmount(money, commissionAmount);double totalAmount = applyFxRate(transferAmount, fxRate);String transactionId = bankService.deposit(totalAmount, destinationAccount); // Second interaction return transactionId;} }我們新的外匯服務必須遵循以下合同
- 根據輸入/輸出合同與貨幣轉換器和銀行轉賬進行交互。
- 對每個服務進行一次呼叫。
測試FX服務的一種方法是調用真實服務,但這意味著測試運行緩慢,并且在執行測試時必須依賴該服務。 有時,調用實時服務不是一種選擇,因為它尚未開發。
聰明的方法是模擬這些合作者(貨幣轉換器和銀行轉賬)并使用模擬框架驗證交互。
使用模擬進行測試的另一個優點是,它可以驗證fxservice是否以預期的方式使用了貨幣和銀行轉帳服務。
讓我們看一下基于模擬的測試。
@Testpublic void transfer_sgd_to_inr() {FXService fxService = new FXService(currencyConverter, bankService, 0.0d);BankAccount account = new BankAccount("1111-22222", "SuperStableBank");expect(currencyConverter.convert(1, "SGD", "INR")).andReturn(50d);expect(bankService.deposit(100d, account)).andReturn("99999");replay(currencyConverter, bankService);String id = fxService.transfer(new Money(SGD, 2d), account, INR);assertEquals("99999", id);verify(currencyConverter, bankService);}該測試是使用EasyMock框架編寫的,并且是模擬來自協作者的答復。
編寫要閱讀的測試
良好測試的重要屬性之一是閱讀愉快。
嘲弄會使目標更加難以實現,因為單元測試的安裝代碼將具有非常復雜的組裝邏輯,這些邏輯將混合一些正常的對象集和某些模擬期望。 我敢肯定,您之前已經看過測試中的功能,該功能可用作類中所有測試所需的設置的轉儲場。
讓我們看一下我們先前使用的一些模擬代碼,并嘗試對其進行改進
expect(currencyConverter.convert(1, "SGD", "INR")).andReturn(50d); expect(bankService.deposit(100d, account)).andReturn("99999"); replay(currencyConverter, bankService);另一種方式
@RegisterExtension JUnit5Mockery context = new JUnit5Mockery();context.checking(new Expectations() {{oneOf(currencyConverter).convert(1, "SGD", "INR");will(returnValue(50d));oneOf(bankService).deposit(100d, account);will(returnValue("99999"));}}); 上面的兩個代碼都在做同樣的事情,但是后來用jmock編寫的代碼具有很好的糖方法來表達同樣的事情。
這有助于使期望保持清潔,并與正在測試的代碼保持一致。 上下文中的協作對象被模擬掉了。
簡單的模式,但在使測試可讀性方面非常有效。
這篇文章中使用的代碼可以在github上找到
翻譯自: https://www.javacodegeeks.com/2020/04/testing-using-mocks.html
總結
- 上一篇: ssdp攻击脚本(ssdp ddos脚本
- 下一篇: 海南房屋备案网查询(海南房屋备案网)