我正在尝试写一些单元测试。该应用程序有许多外部API调用,我想使用NSubstitute模拟它们。问题是这些调用使用了需要在函数中实例化的服务对象,并且不能在替换之后在构造函数中传递。
例如,在下面的代码中,我正在向Quickbooks添加一个帐户:
public async Task AddQuickbooksAsync(int accountId)
{
var qbChannel = await GetQuickbooksChannel();
var account = await GetAsync(accountId);
var quickbooksBO = new QuickbooksBO(qbChannel);
quickbooksBO.AddAccount(account);
quickbooksBO.UpdateRefreshedTokens(qbChannel);
await context.SaveChangesAsync();
}
我想用NSubstitute模拟下面的函数调用,但不知道怎么做:
var quickbooksBO = new QuickbooksBO(qbChannel);
quickbooksBO.AddAccount(account);
我该怎么做?
不能模拟局部变量。您可以创建一个虚拟方法,它将返回QuickbooksBO
并替换它。
public async Task AddQuickbooksAsync(int accountId)
{
var qbChannel = await GetQuickbooksChannel();
var account = await GetAsync(accountId);
var quickbooksBO = GetQbBO(qbChannel);
quickbooksBO.AddAccount(account);
quickbooksBO.UpdateRefreshedTokens(qbChannel);
await context.SaveChangesAsync();
}
public virtual QuickbooksBO GetQbBO(Channel qbChannel)
{
return new QuickBooks(qbChannel);
}
之后你可以在你的服务中替换它:
var s = Substitute.ForPartsOf<Service>();
s.GetQbBO(default).ReturnsForAnyArgs(substituteForQbBO);
你需要弄清楚你想要模仿QuickBooksBO的哪些部分。通常这样的依赖关系应该是接口,没有接口单元测试是相当有限的。
如果QuickbooksBO
方法是虚拟的,你可以这样做得到你的substituteForQbBO
:
var substituteForQbBO = Substitute.ForPartsOf<QuickbooksBO>();
substituteForQbBO.WhenForAnyArgs(x => x.AddAccount(default)).DoNotCallBase();
substituteForQbBO.WhenForAnyArgs(x => x.UpdateRefreshedTokens(default)).DoNotCallBase();