Mock methods with out parameters
Moq is my preferred mocking tool for .NET. Although it has rather good documentation, it doesn't include an example for what I needed, so it took me a while to actually get it working.
Let's try to mock methods in the following interface:
public interface IDependency
{
string MethodWithNoOutParameter(string input);
bool MethodWithOutParameter(string input, out string outParameter);
}
To mock a method with value parameters only, you would use the following syntax:
dependencyMock
.Setup(x => x.MethodWithNoOutParameter(It.IsAny<string>()))
.Returns("output");
If you want to return a value depending on the input parameter instead of a fixed one, you can use a generic Returns()
method instead and provide it a lambda. The generic argument specifies the type of the method parameter:
dependencyMock
.Setup(x => x.MethodWithNoOutParameter(It.IsAny<string>()))
.Returns<string>(p => p);
To mock a method with an out parameter, you also need to provide a value for it, not only the return value. You specify the value of the out parameter with the variable you provide in the Setup()
call:
var outValue = "output";
dependencyMock
.Setup(x => x.MethodWithOutParameter(It.IsAny<string>(), out outValue))
.Returns(true);
If you want to make that value depend on the input parameter, you again need to provide a lambda to the Returns()
method. You need to use a different overload, though, as there's no way to declare an out parameter through a generic argument:
dependencyMock
.Setup(x =>
x.MethodWithOutParameter(
It.IsAny<string>(),
out It.Ref<string>.IsAny
)
)
.Returns(
(string input, out string outParam) =>
{
outParam = input;
return input.Length > 5;
}
);
The parameter types are now declared as part of the lambda signature. This overload of the Returns()
method accepts any delegate type as its parameter. Since C# 10, the compiler can infer the natural type of the lambda expression, so there's no need to manually declare a delegate type as suggested in the Moq documentation anymore.
You can find a working sample project in my GitHub repository. It includes a test for trying out each of the described approaches to mocking.
Out parameters aren't used as often as the value parameters. This also makes methods with them less likely candidates for mocking. Still, it's good to know that this fully supported by Moq.