Ben Biddington

Whatever it is, it's not about "coding"

Posts Tagged ‘software

Mocking and interception

leave a comment »

I have Just been having a look at Moq vs RhinoMocks with respect to mocking concrete members. 

Looks like with either alternative we can mock whatever type we like, however expectations can only be set on certain types of operations on unsealed classes: virtualabstract or interface.

Moq uses Castle Dynamic Proxy which has the limitation:

You can use DynamicProxy to generate lightweight proxies on the fly for one or more interfaces or even concrete classes (but only virtual methods will be intercepted).

Hence only virtualabstract or interface operations can be invoked on a mocked instance. 

The reason for this as described by Daniel Cazzulino:

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. 

Rhinomocks is subject to the same limitation (see Capabilities section):

Attention: Rhino Mocks can only mock interfaces, delegates and virtual methods of classes! (Although it is possible to get work around existing code and easily apply Rhino Mocks, see Example of testing an abstract class)

For example, invoking the following:

MockRepository mocks = new MockRepository();
Artist list = mocks.StrictMock();

// Setup the expectation of a call on the mock
Expect.Call(list.ArtistId).Return(999);
mocks.ReplayAll();

// Evaluate the values from the mock
Assert.AreEqual(999, list.ArtistId);
mocks.VerifyAll();

Results in an error: 

Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).

And mocking an abstract class requires slightly more work.

Mocking System.Object with Rhino Mocks

The following snippet fails:

MockRepository mocks = new MockRepository();
Object mockObject = mocks.StrictMock();

Expect.Call(mockObject.Equals(null)).Return(false);

mocks.ReplayAll();

With exception:

Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).

And yet if I create a type, have it extend System.Object and override GetHashCode:

public class ObjectWrapper : Object
    {
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

 

then that same snippet works. Is this related to the mscorlib thing that TypeMock has?

Advertisements

Written by benbiddington

31 October, 2008 at 09:33