Why does my partial mock have all virtual methods mocked, even if no expectations are set?

1.7k views Asked by At

I have a user control which does some validation in the ValidateChildren method which I would like to test. I have created a partial mock of the user control, but although I am not setting any expectations on the ValidateChildren method, I am simply calling it, it is simply skipped and the code inside the method never executes. To try and understand what is going on I created a simple test, like so:

public class Foo
{        
    public virtual bool Method1()
    {
        throw new NotImplementedException();
    }

    public virtual bool Method2()
    {
        return Method1();
    }
}

and use this to test it:

[Test]
public void TestFooMethods ()
{
    MockRepository m = new MockRepository();
    Foo foo = m.PartialMock<Foo>();

    RhinoMocksExtensions.Expect<Foo,bool>(
                             foo, 
                             delegate (Foo obj)
                             {
                                 return obj.Method1();
                             }
                         ).Return(true);

    Assert.IsTrue (foo.Method2());
}

now I would expect foo.Method1 to be mocked and foo.Method2 not to be. But this always returns false, and if I try and step through in the debugger foo.Method2() is stepped over, and I can't step in to it.

Any ideas why?

2

There are 2 answers

0
Sam Holder On BEST ANSWER

Ok, after some more playing around (perhaps just writing the problem down helped me think more clearly about it) I think I have found the solution.

it seems that I need to call:

RhinoMocksExtensions.Replay (foo);

before I call

Assert.IsTrue (foo.Method2 ());

Perhaps Rhino mocks needs to be told explicitly when virtual methods are being used and not setting up expectations. Not sure why. If anyone knows the reasoning behind this I'd love to know.

Anyway everything seems to be working, so happy days.

2
Jon Cahill On

If you mock an object it will override all the abstract/virtual methods regardless of the type of mock. What you can do though is make an expectation on your method and tell it to execute the original method it is overriding by using:

CallOriginalMethod(OriginalCallOptions.CreateExpectation);

You are not using Rhino Mocks the way it was design which could also be causing you trouble. I have re-written your test in the way it should be written using C# 3.0 and lambda and extension methods:

[TestMethod]
public void TestFooMethods()
{
    //Generate a new Mock to test against
    Foo foo = MockRepository.GenerateMock<Foo>();

    //Expect a call to Method1 on object foo and return true
    foo.Expect(f => f.Method1()).Return(true);
    //Expect a call to Method2 on object foo and call the original method
    foo.Expect(f => f.Method2()).CallOriginalMethod(OriginalCallOptions.CreateExpectation);

    Assert.IsTrue(foo.Method2());

    //Verify all our expectations on foo
    foo.VerifyAllExpectations();
}