Home > Software design >  Moq, mockin an abstract class : the mocked object does cannot use methods implemented in the abstrac
Moq, mockin an abstract class : the mocked object does cannot use methods implemented in the abstrac

Time:03-08

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.

  • Related