Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq a base class function from a derived class

Tags:

c#

moq

I am new to Moq and I just watched the pluralsight video on Moqing so I felt empowered to go and write some tests. I have a Base Class let’s say Sheet which implements an interface ISheet. Sheet is the base class for pages:

abstract class Sheet: ISheet
{
    public virtual void CreateSheet()  // Defined in ISheet
    {
    }
    public virtual void BuildSheet() // Defined in ISheet
    {
    }
    //and some abstract methods, etc.
}

public class Page : Sheet
{
    public override void CreateSheet()
    {
        BuildSheet(); // Base class implementation
    }
}

I overrode one of the methods from the base class which is CreateSheet(), but I want to test that the BuildSheet() method in the base class is called from my derived class:

So in my Test Class, I Moq the SUT instead of the interface

var MockSheet = new Moq<Page>();

call the method:

var actual = MockSheet.Object.CreateSheet(); 

Then verify

MockSheet.Verify(x => x.BuildSheet(), Times.AtLeastOnce);

Instead I get MockException “Expected Invocation on the mock at least once but was never performed. The CreateSheet method never gets called. If I change he CreateSheet method to:

public void CreateDocSheet() // removed override
{
    BuildSheet() // base classses implementation
}

And in the test call:

var actual = MockSheet.Object.CreateDocSheet();  

It works. I don’t understand why. I believe that functionally that this is a valid way of coding, I have sheet, that has 2 pages, I have an Interface that defines all the functions and properties that should be implemented, I implement these functions in the base class, but not all methods need to implemented in the derived classes so, some method are overridden and some use the base class implementation. Please explain why it is an issue to use the overridden version of the function?

like image 346
user3666407 Avatar asked Jan 29 '15 20:01

user3666407


2 Answers

If you change

var MockSheet = new Moq<Page>();

into

var MockSheet = new Moq<Page> { CallBase = true, };

your mock (which you can think of as a derived class of Page) will call the implementation from Page in the mock's own override of CreateSheet.

The default behavior (if you do not change CallBase) is for Moq to override every method and property it can, and use an empty implementation. Setting CallBase to true makes Moq call the Page implementation instead, like I said.

(Of course, use MockSheet.Setup(x => x.CreateDocSheet()).Callback(() => { /* something */ }) if you want CreateDocSheet to do something non-trivial.)

In the case where you removed the virtual modifier from CreateSheet, Moq can no longer override or mock this member. Think of it: How could Moq "mock" a non-virtual method? Therefore, the call bypasses Moq's class completely.

like image 173
Jeppe Stig Nielsen Avatar answered Oct 01 '22 14:10

Jeppe Stig Nielsen


Moq is for imitating a dependency or dependencies of your system under test so that you can isolate that from the rest of your application or externalities, not for replacing your system under test. It's not the right tool for what you are trying to do here.

like image 38
tom.dietrich Avatar answered Oct 01 '22 12:10

tom.dietrich