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?
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.
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.
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