夜神模拟器模拟安卓测试
如果使用正确的方法,模拟对象将非常有用。 我在需要驱动软件开发使用的帖子中分享了一些使用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;
}
}
我们新的外汇服务必须遵循以下合同
- 根据输入/输出合同与货币转换器和银行转账进行交互。
- 对每个服务进行1次呼叫。
测试FX服务的一种方法是调用真实服务,但这意味着测试运行缓慢,并且在执行测试时必须依赖于服务。 有时调用实时服务不是一种选择,因为它尚未开发。
聪明的方法是模拟这些合作者(货币转换器和银行转账)并使用模拟框架验证交互。
使用模拟进行测试的另一个优点是,它可以验证fxservice是否以预期的方式使用了货币和银行转账服务。
让我们看一下基于模拟的测试。
@Test
public 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
夜神模拟器模拟安卓测试