NSubstitute - 模拟任何参数的行为

17

我正在尝试使用NSubstitute来模拟IConfigurationProvider。我需要这个方法bool TryGet(string key, out string value)能够返回不同键的值。因此类似于这样的东西:

var configProvider = Substitute.For<IConfigurationProvider>();
configProvider.TryGet("key1", out Arg.Any<string>()).Returns(x => 
    { x[1] = "42"; return true; });

但是这段代码无法编译。

我需要模拟的方法实际上将输出参数设置为适当的值,无论该参数是什么 - 这是一种依赖性,被测试单元使用自己的参数调用此方法,我只想让它通过填充正确的密钥来“返回”(即通过填充输出参数返回)正确的价值。

这将更好地解释问题:

var value = "";
var configProvider = Substitute.For<IConfigurationProvider>();
configProvider
.TryGet("key1", out value)
.Returns(x => { 
    x[1] = "42"; 
    return true; 
});

var otherValue = "other";
configProvider.TryGet("key1", out value);
configProvider.TryGet("key1", out otherValue);

Assert.AreEqual("42", value);      // PASS.
Assert.AreEqual("42", otherValue); // FAIL.

我需要这两个断言都为真,因为这个方法将被测试类使用,而且它可以传递任何输出参数,我只需要用 "42" 填充它。


configProvider.TryGet("key1", out Arg.Any<string>()) 不是有效的 C# 语法。您需要为 out 参数使用实际变量。 - Nkosi
2个回答

26

configProvider.TryGet("key1", out string value)是无效的C#语法,这就是为什么它不能编译。

你需要为out参数使用实际变量。

以下代码在测试时可行。

//Arrange            
var expectedResult = true;
var expectedOut = "42";
var actualOut = "other";
var anyStringArg = Arg.Any<string>();
var key = "key1";
var configProvider = Substitute.For<IConfigurationProvider>();
configProvider
    .TryGet(key, out anyStringArg)
    .Returns(x => {
        x[1] = expectedOut;
        return expectedResult;
    });

//Act
var actualResult = configProvider.TryGet(key, out actualOut);

//Assert
Assert.AreEqual(expectedOut, actualOut); // PASS.
Assert.AreEqual(expectedResult, actualResult); // PASS.

6

从 NSubstitute 4+ 版本开始,此功能已被支持:

Matching out and ref args


Argument matchers can also be used with out and ref (NSubstitute 4.0 and later with C# 7.0 and later).

calculator
    .LoadMemory(1, out Arg.Any<int>())
    .Returns(x => {
        x[1] = 42;
        return true;
    });

var hasEntry = calculator.LoadMemory(1, out var memoryValue);
Assert.AreEqual(true, hasEntry); Assert.AreEqual(42, memoryValue); 

来源

请注意上面使用的参数索引(x [1] = 42;),该数组包括输入和输出变量,但您只能设置out变量的值。


2
看起来编译器的更新可能已经消除了那个使用选项,至少在返回值是某种对象的情况下。我在Visual Studio 2019 v16.9.6中遇到了CS1510错误导致无法编译。 - Richard J Foster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接