views:

360

answers:

2

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?

+1  A: 

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();
}
Jon Cahill
This doesn't seem to work as I would have thought. I get a problem:Rhino.Mocks.Exceptions.ExpectationViolationException : Foo.Method1(); Expected #1, Actual #0.when I call RhinoMocksExtensions.VerifyAllExpectations(foo);and I still need to call RhinoMocksExtensions.Replay (foo); before I verify the expectations. I'm a bit puzzled as to why though, as if I step through the code Method2 is called and I can step in and see that it is calling Method1(), so why it claims its not called I don't know.
Sam Holder
I have updated this answer so it shows the full test which I have tested and works. If you aren't using C# 3.0 then I can update the answer to also include the test in an old style
Jon Cahill
A: 

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.

Sam Holder