hi I have a code similar to the following:
public abstract class MyAbstractClass
{
public virtual string DoSomething(string s1, string s2)
{
return this.DoSomethingElse(s1 s2);
}
protected abstract string DoSomethingElse(string s);
}
[TestMethod]
public void Test()
{
var myMock = new Mock<MyAbstractClass>();
myMock.Protected().Setup<string>("DoSomethingElse", ItExpr.IsAny<string>()).Returns<string>(x => $"{x} I did it.");
var result = myMock.Object.DoSomething("a", "b");
}
I would expect the result in the test to be "ab I did it", but I get back a null. I noticed that if remove the "virtual" to the "DoSomething" method, than it would return as expected. The problem is that I need this method to be virtual. And honestly in my understanding of how moq work it should return the "ab I did it", but maybe I am missing something.
Any idea? Thanks
CodePudding user response:
The reason is because you're calling the DoSomething
method using the mock object, but because you haven't told the mock object to use the real implementation or Setup
it, it's just going to "do nothing" (ie return null) by default.
The quick way to solve this is by setting the CallBase = true
property for the mock object. Then, any method that isn't Setup
will use the real implementation.
var myMock = new Mock<MyAbstractClass>() { CallBase = true };
myMock
.Protected()
.Setup<string>("DoSomethingElse", ItExpr.IsAny<string>())
.Returns("DoSomethingElseResult");
Console.WriteLine("DoSomething: " myMock.Object.DoSomething("a", "b"));
This will print "DoSomething: DoSomethingElseResult", which should be exactly what you want. The mock object runs DoSomething
using the real implementation, and the real implementation of DoSomething
runs the mocked implementation of DoSomethingElse
.