35

How can I do this in Moq?

Foo bar = new Foo();
Fake(bar.PrivateGetter).Return('whatever value')

It seems I can only find how to mock an object that was created via the framework. I want to mock just a single method/property on a concrete object I've created.

In TypeMock, I would just do Isolate.WhenCalled(bar.PrivateGetter).Returns('whatever value').

Any ideas?

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
dferraro
  • 6,357
  • 11
  • 46
  • 69

3 Answers3

57

You should use Moq to create your Mock object and set CallBase property to true to use the object behavior.

From the Moq documentation: CallBase is defined as “Invoke base class implementation if no expectation overrides the member. This is called “Partial Mock”. It allows to mock certain part of a class without having to mock everything.

Sample code:

    [Test]
    public void FailintgTest()
    {
        var mock = new Moq.Mock<MyClass>();
        mock.Setup(m => m.Number).Returns(4);
        var testObject = mock.Object;
        Assert.That(testObject.Number, Is.EqualTo(4));
        Assert.That(testObject.Name, Is.EqualTo("MyClass"));
    }

    [Test]
    public void OKTest()
    {
        var mock = new Moq.Mock<MyClass>();
        mock.Setup(m => m.Number).Returns(4);
        mock.CallBase = true;
        var testObject = mock.Object;
        Assert.That(testObject.Number, Is.EqualTo(4));
        Assert.That(testObject.Name, Is.EqualTo("MyClass"));
    }

    public class MyClass
    {
        public virtual string Name { get { return "MyClass"; } }

        public virtual int Number { get { return 2; } }
    }
gsk
  • 1,233
  • 15
  • 32
Ariel Popovsky
  • 4,787
  • 2
  • 28
  • 30
  • Thanks, I will try this. Makes TypeMock look more and more tempting though. Ugh! – dferraro Mar 17 '10 at 19:14
  • 1
    This didn't work - it gave error message on the mock.Setup() line (in second example) "Test method CRMFundOfFundPluginsUnitTest.FoFPluginBaseTest.SetMissingTargetValuesTest1 threw exception: System.ArgumentException: Invalid setup on a non-overridable member: m => m.InputTargetDE.". Any idea why? – dferraro Mar 18 '10 at 19:56
  • 6
    Make sure the methods you are mocking are virtual so Moq will be able to override them. – Ariel Popovsky Apr 12 '10 at 14:58
  • 1
    This doesn't actually answer the question. -- This calls base methods, but it requires that you let Moq create the object. -- The scenario that the OP showed has something externally creating the mock object. – BrainSlugs83 Feb 24 '17 at 22:07
  • Doesn't answer the question maybe, but it is close enough for many situations and solved the problem for me. – Martin Capodici Jul 20 '17 at 06:36
13

Only TypeMock Isolator (and perhaps Moles) can perform these stunts. Normal dynamic mock libraries can only mock virtual and abstract members.

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Good to Know - wish there was more info on Moles out there - haven't heard anything on it at all yet as far as people using it here on SO – dferraro Mar 17 '10 at 19:15
  • FWIW, here's the official site: http://research.microsoft.com/en-us/projects/moles/ – Mark Seemann Mar 17 '10 at 19:51
  • That Moq cannot do this is simply not true anymore. – MushinNoShin Sep 30 '14 at 23:57
  • @MushinNoShin Oh, I didn't know that! Can you provide a link? – Mark Seemann Oct 01 '14 at 10:06
  • Check the most upvoted answer in this question :) It only works if there's a parameterless constructor available however, which is the case for this question. – MushinNoShin Oct 03 '14 at 17:33
  • 1
    @MushinNoShin Yes, and make sure to also read the comments from the OP: "This didn't work". That answer explains how to Moq virtual members, whereas the OP asks about private members. The link in my (accepted) answer explains what is technically possible. – Mark Seemann Oct 04 '14 at 09:58
  • @MarkSeemann Ah, you're right, I guess I glossed over the `bar.PrivateGetter` part. Thanks! – MushinNoShin Oct 04 '14 at 14:02
3

Moles can also replace private methods as long as the types on the signature are visible. So in this case, it would look like this:

MFoo bar = new MFoo { // instantiate the mole of 'Foo'
    PrivateGetterGet = () => "whatever value" // replace PrivateGetter {get;}
};
Foo realBar = bar; // retrive the runtime instance
...

If you are looking for more information on Moles, start with the tutorials at http://research.microsoft.com/en-us/projects/pex/documentation.aspx.

Peli
  • 2,465
  • 16
  • 17