Home > .net 3.5, c#, General Development, Visual Studio 2008 > MoQ Mocks – Use virtual method or interfaces?

MoQ Mocks – Use virtual method or interfaces?

May 6, 2008

I’ve switched over and am using MoQ full time now on my projects and LOVE it.  The lambda expressions may seem strange to others, but I like that I can read my code, left to right, and it’s almost verbatium to what I want to do.

The one snafu that really bugs me is when testing classes that are based off of a base class rather than an interface.  For example, my LINQ business layers fall back onto a prototype over on the MSFT Code Gallery and the Microsoft Dynamic Query libraries (which is part of the VS2008 samples, just add the class file into your project).

Unfortunately, the base class library has everything has static methods.  That’s no good for testing.  However, that’s not enough.  I kept getting the following error:

System.ArgumentException: Invalid expectation on a non-overridable member.

Say huh?  Non-overridable?  Why’s it trying to override the method?

I finally found the answer over on the MoQ Google Groups—”[Castle] DynamicProxy can not intercept methods calls to non virtual, non abstract methods”.

Daniel Cazzulino goes on to explain:

it’s a limitation of the CLR since its inception: there’s no built-in
interception mechanism.

so, the interception mechanism we use is auto-generated classes that inherit from the types to mock, and override all members to provide the interception. that’s why they need to be virtual.

we’re reusing the interception library from Castle DynamicProxy for doing that.

Well, that explains that, but I’m not sure I like decorating my classes simply to enable mocking. 

public virtual bool Add(int studentId, string enteredBy) { }

The mock and test then look like:

[TestMethod]

public void Reports_AddReport()

{

       var mock = new Mock<ReportsController>();

       mock.Expect(x => x.Add(studentId, enteredBy)).Returns(true);

      

       Assert.IsTrue(mock.Object.Add(studentId, enteredBy));

}

What would be a better solution? 

In my opinion, taking the base class and pushing the members up into an interface, then mocking the interface would be best.

With the methods nicely tucked into a new IReportsController interface and the virtuals banished from our base class, our test only changes slightly, but without opening up the methods in the base class to override.

[TestMethod]

public void Reports_AddReport()

{

       var mock = new Mock<IReportsController>();

       mock.Expect(x => x.Add(studentId, enteredBy)).Returns(true);

      

       Assert.IsTrue(mock.Object.Add(studentId, enteredBy));

}

Are there times where virtual methods would be a better idea?

  1. Robert Leahey
    June 18, 2008 at 9:18 am

    Greetings. I’m just starting to experiment with MoQ and have run into this issue. I’m wondering what you might suggest in a situation where a system class with a non-overridable method needs to be mocked. I haven’t run into that yet, but it seems like an inevitable roadblock to using MoQ (which I, too, am really enjoying)

  2. June 18, 2008 at 9:53 am

    @Robert-

    I came across this a while back:

    http://groups.google.com/group/moqdisc/browse_thread/thread/1e92be1795cb948f/418a913ca29e666d?show_docid=418a913ca29e666d

    I think it, over and above what Daniel mentions in his post, depends on what the method is and whether or not it is interfaced. If it’s interfaced, mock the interface.

    Could you post an example, or pseudo code, of what you’re thinking? I haven’t ran into any issues so far…šŸ™‚

  3. Robert Leahey
    June 18, 2008 at 10:24 am

    Well, that MarshalByRefObject caveat might solve some of my imagined problems, thanks.
    I don’t really have an example yet; I’m looking forward…
    However, I’m reminded of an old project where we mocked up an entire DataSet complete with tables and mocked records, etc. for testing an object that did a bit of processing on that DataSet. As I thought about this issue with not being able to mock calls to non-overridable methods, that scenario came to mind and I started wondering whether that would have even been possible using MoQ (if some method we needed to mock in the DataSet or its tables was non-overridable, you see.)

  4. Ligo Rotres
    July 29, 2008 at 7:35 am

    Anyone knows how RhinoMocks does it? They are able to intercept non-overridable calls.

  5. August 11, 2008 at 5:09 pm

    @Ligo:
    I’m not sure it does. It also depends on Castle.DynamicProxy and whatever limits Moq sure does limits Rhino Mocks.

    @Everyone:
    I’ve been hand rolling my mocks a long time. Recently, started using Rhino.
    See, I need a partial mock (stub). Me & My team use mocks for classes under parallel development. One (non-virtual) method throws an error which I want to intercept and stub.

    If this method (non-virtual) is part of an Interface, can’t I do something like this?

    Mock manager = new Mock(new EventManager());
    manager.Stub(x=>x.SomeMethod()).Return(delegate() { //Do something here });

    The intent here is ALL calls to the interface is routed to the original object except for the method stubbed (SomeMethod() in this case).

    Regards, Vyas

  6. October 19, 2008 at 12:02 am

    With Typemock Isolator you can mock anything, including static calls and sealed classes. It’s a different technology than Moq and Rhino, which allows it to do this.

    Gil Zilberfeld
    Typemock

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: