NSubstitute是否支持ref参数?

时间:2010-09-24 18:45:35

标签: .net unit-testing nsubstitute

我的iterface中有以下方法签名:

void SetItem(ref AddressItem item);

我像这样做一个参数约束:

IAddAddressForm form = Substitute.For<IAddAddressForm>();
AddressItem item = null;
form.SetItem(Arg.Is(item));

但由于裁判失败了。如果我拿出ref,那就行了。但我需要在这里通过引用。

任何想法如何得到这个?

附注:我的最终目标是如果传入的值为null,则在SetItem中抛出异常。如果你可以提供帮助,那么你会得到额外的积分!

1 个答案:

答案 0 :(得分:10)

NSubstitute没有直接支持arg匹配ref参数,但一般来说它可以正常使用它们。

我假设您必须按照问题中的说明使用ref,但很明显,如果您可以避免ref您的API会更简单,测试也会更简单(无论框架如何)你用)。

在回答您的直接问题时,您可以通过将第二个代码示例更新为:

来传递参考
form.SetItem(ref item);

对于你的旁注,请确保你没有试图在你的替代品中加入过多的行为。我发现每当我这样做时,我需要简化我正在测试的类和它的依赖项之间的通信。 (或者如果我真的需要一个虚假对象中的大量逻辑,我会用一个代码而不是生成它;它通常可以更简单。)

有几种方法可以让这个调用抛出异常:

form.When(x => x.SetItem(ref item)).Do(x => { throw new ArgumentNullException(); });

仅在使用null ref调用时才会抛出异常。你也可以根据传递的参数选择性地添加这种行为,虽然我建议不要这样做,因为这可能是你过分投入替代品的一个迹象。

form.WhenForAnyArgs(x => x.SetItem(ref item))
    .Do(x => {
        if (x[0] == null)
            throw new ArgumentNullException();
    });

最后,如果您只是想在IAddAddressForm抛出一个arg null异常时检查您正在测试的类是否正确响应,我可能只是这样做:

form
    .WhenForAnyArgs(x => x.SetItem(ref item))
    .Do(x => { throw new ArgumentNullException(); });

这样你就不关心参数是什么,你只是想确保你正在测试的代码对这种情况做出正确的反应。

希望这有帮助。

SIDE NOTE:

如果你想为Arg.Any<AddressItem>()out参数使用arg匹配器(如ref),你需要在调用本身之外定义它(这可能是一点点容易出错:你需要确保按照调用它们的顺序定义匹配器:

        IAddAddressForm form = Substitute.For<IAddAddressForm>();
        AddressItem item = Arg.Is<AddressItem>(y => y.Number == 14);
        form
            .When(x => x.SetItem(ref item))
            .Do(x => { throw new ArgumentNullException(); });
        var address = new AddressItem { Number = 14 };
        form.SetItem(ref address);