如何从对象中替换被测试函数中的函数调用



我正在尝试写一些单元测试。该应用程序有许多外部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();

最新更新