I'm trying to mock IConfigurationProvider
with NSubstitute. I need the method bool TryGet(string key, out string value)
to return values for differing keys. So something like this:
var configProvider = Substitute.For<IConfigurationProvider>();
configProvider.TryGet("key1", out Arg.Any<string>()).Returns(x =>
{ x[1] = "42"; return true; });
but this does not compile. I need the mocked method to actually set the out parameter to the appropriate value, regardless of what that parameter is - it's a dependency, the unit under test calls this method with its own parameters and I just want it to "return" (as in return by filling the out parameter) correct values for keys.
This should give more perspective on the problem:
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.
I need both assertions to be true, since this method will be used by the tested class and it's free to pass any out parameter it wants, I just need to fill it with "42".
configProvider.TryGet("key1", out Arg.Any<string>())
is not valid C# syntax, which is why it wont compile.
You need to use an actual variable for the out parameter.
The following works when tested.
//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.
As of NSubstitute 4+ this is supported out the box:
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);
Source
Make sure you note the argument index used above (x[1] = 42;
), this array includes the input and output variables but you can only set the value of an out
variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With