58

I really appreciate Moq's Loose mocking behaviour that returns default values when no expectations are set. It's convenient and saves me code, and it also acts as a safety measure: dependencies won't get unintentionally called during the unit test (as long as they are virtual).

However, I'm confused about how to keep these benefits when the method under test happens to be virtual.
In this case I do want to call the real code for that one method, while still having the rest of the class loosely mocked.

All I have found in my searching is that I could set mock.CallBase = true to ensure that the method gets called. However, that affects the whole class. I don't want to do that because it puts me in a dilemma about all the other properties and methods in the class that hide call dependencies: if CallBase is true then I have to either

  1. Setup stubs for all of the properties and methods that hide dependencies -- Even though my test doesn't think it needs to care about those dependencies, or
  2. Hope that I don't forget to Setup any stubs (and that no new dependencies get added to the code in the future) -- Risk unit tests hitting a real dependency.

What I think I want is something like:
mock.Setup(m => m.VirtualMethod()).CallBase();
so that when I call mock.Object.VirtualMethod(), Moq calls into the real implementation...

Q: With Moq, is there any way to test a virtual method, when I mocked the class to stub just a few dependencies? I.e. Without resorting to CallBase=true and having to stub all of the dependencies?


Example code to illustrate
(uses MSTest, InternalsVisibleTo DynamicProxyGenAssembly2)

In the following example, TestNonVirtualMethod passes, but TestVirtualMethod fails - returns null.

public class Foo
{
    public string NonVirtualMethod() { return GetDependencyA(); }
    public virtual string VirtualMethod() { return GetDependencyA();}

    internal virtual string GetDependencyA() { return "! Hit REAL Dependency A !"; }
    // [... Possibly many other dependencies ...]
    internal virtual string GetDependencyN() { return "! Hit REAL Dependency N !"; }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestNonVirtualMethod()
    {
        var mockFoo = new Mock<Foo>();
        mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);

        string result = mockFoo.Object.NonVirtualMethod();

        Assert.AreEqual(expectedResultString, result);
    }

    [TestMethod]
    public void TestVirtualMethod() // Fails
    {
        var mockFoo = new Mock<Foo>();
        mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
        // (I don't want to setup GetDependencyB ... GetDependencyN here)

        string result = mockFoo.Object.VirtualMethod();

        Assert.AreEqual(expectedResultString, result);
    }

    string expectedResultString = "Hit mock dependency A - OK";
}
Daryn
  • 4,791
  • 4
  • 39
  • 52
  • Just a brief of what your/my need is all about: Need a `CallBase` version when mocking that instead of **"Invoke base class implementation if no expectation overrides the member"**, so-called _Partial Mocks_, please just call the base implementation of the mocked members! I would like to name the new function as `CallBaseOnMockedMemberOnly` :D – Nam G VU Nov 04 '10 at 04:50

3 Answers3

32

I believe Lunivore's answer was correct at the time it was written.

In newer versions of Moq (I think since version 4.1 from 2013) it is possible to do what you want with the exact syntax you propose. That is:

mock.Setup(m => m.VirtualMethod()).CallBase();

This sets up the loose mock to call the base implementation of VirtualMethod instead of just returning default(WhatEver), but for this member (VirtualMethod) only.


As user BornToCode notes in the comments, this will not work if the method has return type void. When the VirtualMethod is non-void, the Setup call gives a Moq.Language.Flow.ISetup<TMock, TResult> which inherits the CallBase() method from Moq.Language.Flow.IReturns<TMock, TResult>. But when the method is void, we get a Moq.Language.Flow.ISetup<TMock> instead which lacks the desired CallBase() method.

Update: andrew.rockwell notes below that it works now for void methods, and apparently that was fixed in version 4.10 (from 2018).

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • I'm no longer doing C# in my day job so not in the best position to verify, but I'd be happy to update the accepted answer to reflect current reality. If anyone else can chime in to confirm @Jeppe's new answer, please do so! —Thanks – Daryn Aug 14 '15 at 17:08
  • @Daryn: I can confirm it works, just tried it. Reading this question ended up accidentally helping me understand an unrelated problem (why are all my non-virtual methods calling their base implementation?), so thought I'd return the favour and give this a try :) – Craig Brett Feb 26 '16 at 15:04
  • Thanks for reviving that @Craig, I'll mark as accepted answer based on your confirmation (sorry for the wait @Jeppe!) – Daryn Feb 29 '16 at 07:52
  • 1
    It doesn't work if VirtualMethod() returns void. Is there any way to make it work on void methods as well? – BornToCode Jun 02 '16 at 12:43
  • 2
    @BornToCode Apparently not. I mentioned this shortcoming in my answer. It almost feels like a bug (or missing feature) in Moq. – Jeppe Stig Nielsen Jun 02 '16 at 13:21
  • There's a hacky way to make it work for `void` methods, and I've posted it in [an answer](https://stackoverflow.com/a/45252441/1394393). If you'd like to incorporate it into yours, I'll delete mine. – jpmc26 Jul 22 '17 at 08:34
  • 1
    Worked for me on a `void` method as of today – andrew.rockwell Jul 29 '19 at 19:30
8

Since nobody's answered this question for ages and I think it deserves an answer, I'm going to focus on the highest-level question you asked: how to keep these benefits when the method under test happens to be virtual.

Quick answer: you can't do it with Moq, or at least not directly. But, you can do it.

Let's say that you have two aspects of behaviour, where aspect A is virtual and aspect B is not. That pretty much mirrors what you've got in your class. B can use other methods or not; it's up to you.

At the moment, your class Foo is doing two things - both A and B. I can tell that they're separate responsibilities just because you want to mock A out and test B on its own.

Instead of trying to mock out the virtual method without mocking out anything else, you can:

  • move behaviour A into a separate class
  • dependency inject the new class with A into Foo through Foo's constructor
  • invoke that class from B.

Now you can mock A, and still call the real code for B..N without actually invoking the real A. You can either keep A virtual or access it through an interface and mock that. This is in line with the Single Responsibility Principle, too.

You can cascade constructors with Foo - make the constructor Foo() call the constructor Foo(new A()) - so you don't even need a dependency injection framework to do this.

Hope this helps!

Lunivore
  • 17,277
  • 4
  • 47
  • 92
  • Just to check: you're confirming that if the method under test is virtual, and we're using Mock, we do HAVE to set CallBase to true? – Daryn Oct 20 '10 at 21:13
  • I'm suggesting that if you're calling CallBase in the first place, there's probably a different way to get the same benefit and which probably leads to a design of code that works in most contexts. Perhaps you have one of those rare contexts which absolutely requires CallBase - I don't know. Can you tell me more about why CallBase for a method would be the simplest solution to your problem? – Lunivore Oct 20 '10 at 23:40
  • Not the OP, but I think this question is still valid: CallBase is the simplest solution when you have fairly atomic business logic that is extremely cumbersome to test via a single entry point. Splitting to classes a good principle, but can sometimes be prohibitively costly with legacy code, or at least a dangerous starting point. Excessive splitting also leads to type diarrhea, which makes the solution far harder to read (e.g. a mesh of 10 interdependent classes where there is only one sensible entry point). – Jouni Heikniemi Mar 02 '13 at 11:37
  • @JouniHeikniemi Splitting methods into a separate class is something Resharper will do *for* you, so I can't see how it would be unsafe. If it compiles, you've done the job. If you also name the class after what it's doing, the solution will be easier to read rather than harder. There shouldn't be a mesh of interdependent classes as a result; just one helper class where a long method used to be. Also works well with large blocks of discreet functionality. Mind you, I refactor legacy code and bring it under test *for fun*... – Lunivore Mar 02 '13 at 11:47
  • Not sure how your spare time habits are relevant, but glad you enjoy it :-) Check out https://gist.github.com/jouniheikniemi/5108310 to see my point. R# will give you some help but not much; if you go down the Make static / Move / Make non-static route, you end up passing instances here and there instead of getting them as constructor parameters (often more sensible, and supports IoC as well). Also, R# doesn't make things safe: you CAN introduce duplicate copies of instance variables as well as break access (though compiler catches this). – Jouni Heikniemi Mar 07 '13 at 14:21
  • But that said, I definitely agree that splitting to classes should be the primary approach! It's just that some codebases need heavy refactoring to do that properly, and such changes are not always possible within the mandated timeframe or risk threshold. This is, of course, less of an issue if you refactor just for fun. – Jouni Heikniemi Mar 07 '13 at 14:25
  • "Fun" doesn't have to mean "spare time". It's just something I really enjoy doing, and if it needs doing I volunteer. All software needs cleaning up eventually. Well, okay, so I *also* do it in my spare time. 10,000 hours to become an expert, right? And then there's open source. Time to go play... – Lunivore Mar 08 '13 at 23:34
  • Yeah, I definitely agree! There is always more source code to fix, and OS projects particularly benefit from good refactoring. What you're - we're - doing is of benefit for the whole development world. I was just trying to discuss the best methodologies for that :-) – Jouni Heikniemi Mar 11 '13 at 05:15
  • OK, I've actually looked at the code. A little bit of renaming for what's actually going on - `next` instead of `get` for example - and it isn't that bad, or that tricky. Will have a go if I get time. – Lunivore Mar 11 '13 at 10:05
  • 1
    Sure, great! But please realize that my gist was an extremely simplified example, only intended to visualize the limitations of refactoring tools. I happen to be facing a 2500+ line file - a single class - with at least 10 methods that I could consider testing separately. But between ~15 shared data members (some located in the base class, which also has its own set of methods) and numerous cross-calls (some of which delegate-based), I find it extremely hard to split the class without introducing significant change risks. For this, CallBase actually feels like a good _first_ approach. – Jouni Heikniemi Mar 11 '13 at 10:59
-1

There is a way to call the real method and have a call back when the method is void, but it's really hacky. You have to make your call back call it explicitly and trick Moq into calling the real one.

For example, given this class

public class MyInt
{
    public bool CalledBlah { get; private set; }

    public virtual void Blah()
    {
        this.CalledBlah = true;
    }
}

You can write your test this way:

[Test]
public void Test_MyRealBlah()
{
    Mock<MyInt> m = new Mock<MyInt>();
    m.CallBase = true;

    bool calledBlah = false;
    m.When(() => !calledBlah)
        .Setup(i => i.Blah())
        .Callback(() => { calledBlah = true; m.Object.Blah(); })
        .Verifiable();

    m.Object.Blah();

    Assert.IsTrue(m.Object.CalledBlah);
    m.VerifyAll();
}

The key aspect is that you track if the fake version has been called, and then you set the mock up to not call the fake if it's already been called.

You can still do something similar if you take args and the value matters:

public class MyInt
{
    public List<int> CalledBlahArgs { get; private set; }

    public MyInt()
    {
        this.CalledBlahArgs = new List<int>();
    }

    public virtual void Blah(int a)
    {
        this.CalledBlahArgs.Add(a);
    }
}

[Test]
public void Test_UpdateQueuedGroups_testmockcallback()
{
    Mock<MyInt> m = new Mock<MyInt>();
    m.CallBase = true;

    List<int> fakeBlahArgs = new List<int>();

    m.Setup(i => i.Blah(It.Is<int>(a => !fakeBlahArgs.Contains(a))))
        .Callback<int>((a) => { fakeBlahArgs.Add(a); m.Object.Blah(a); })
        .Verifiable();

    m.Object.Blah(1);

    Assert.AreEqual(1, m.Object.CalledBlahArgs.Single());
    m.Verify(b => b.Blah(It.Is<int>(id => 1 == id)));
}
jpmc26
  • 28,463
  • 14
  • 94
  • 146
  • Interesting. However, you set `m.CallBase = true;`, but the asker explicitly said he wanted a solution where you do not set `CallBase` to True because that affects all the other `virtual` members as well, and the asker wanted to avoid that. – Jeppe Stig Nielsen Jul 22 '17 at 12:44