NSubstitute-模拟任何参数的参数行为

V0l*_*dek 7 c# unit-testing nsubstitute .net-core

我正在尝试IConfigurationProvider使用NSubstitute。我需要该方法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; });
Run Code Online (Sandbox Code Playgroud)

但这无法编译。我需要一个模拟方法来实际将out参数设置为适当的值,而不管该参数是什么-它是一个依赖项,被测单元使用自己的参数调用此方法,而我只是希望它“返回”(如通过填充out参数返回)正确的键值。

这应该为该问题提供更多视角:

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.
Run Code Online (Sandbox Code Playgroud)

我需要两个断言都是正确的,因为该方法将由测试的类使用,并且可以自由传递它想要的任何out参数,我只需要用“ 42”填充即可。

Nko*_*osi 8

configProvider.TryGet("key1", out Arg.Any<string>()) 不是有效的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.
Run Code Online (Sandbox Code Playgroud)


Lia*_*iam 6

从 NSubstitute 4+ 开始,这是开箱即用的支持:

匹配和引用参数


参数匹配器也可以与 out 和 ref 一起使用(NSubstitute 4.0 及更高版本与 C# 7.0 及更高版本一起使用)。

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); 
Run Code Online (Sandbox Code Playgroud)

来源

确保记下上面使用的参数索引 ( x[1] = 42;),该数组包含输入和输出变量,但只能设置out变量的值。

  • 看来后来对编译器的更新可能已经消除了该使用选项,至少在返回值是某种对象的情况下是如此。我在 Visual Studio 2019 v16.9.6 中编译失败,并出现 CS1510 错误。 (2认同)