Ben Biddington

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

Posts Tagged ‘mocking

Particle physics, mocks and stubs

leave a comment »

Steve Freeman had interesting analogy in TDD 10 years later (17m30s, slide 26: The origins of mock objects). He describes mocked unit test being “rather like particle physics”.

You fire something at a particle, things splinter off and you can detect what happens…

mocks-and-stubs

A mock is used to both detect the emissions from the system under test (SUT), and verify expectations. Additionally, a mock object may perform stub duties. This doesn’t quite fit, since fission is one-way.

Testing “by detection” like this is considered behaviour verification: verifying collaborations between the SUT and other objects.

To be testable in such a manner:

  • Requires the ability to isolate the SUT sufficiently, i.e., detach it completely from its context and collaborators. A test fixture should be able to create the SUT easily by itself.
  • Then the SUT should minimize concrete dependencies.
  • Collaborators must be designed in such a way to allow a mock to be generated that can intercept interactions. This means identifying the abstraction(s) for collaborators.
  • Mock is a stub in the sense that it needs to stand in for a real (if inert) object. But a mock is also a “detector” and is used as the means of assertion.
  • Stub queries and mock actions. “we mock when the service changes the external world; we stub when it doesn’t change the external world – stub queries and mock actions”

References

Written by benbiddington

12 September, 2009 at 15:15

Posted in development

Tagged with , , , ,

RhinoMocks — repeat times

with one comment

My pair and I discovered some unexpected behaviour with repeat times yesterday. It appears repeat times behaves differently when using the Expect than it does when using AAA.

Our expectation fails, i.e., the following test passes, when the actual number of invocations exceeds expected:

[Test]
public void expect_repeat_n_times_does_not_work_when_actual_greater_than_expected() {
    const Int32 ActualTimesToCall = 6;
    const Int32 ExpectedTimesToCall = 4;

    var mock = MockRepository.GenerateMock<IExample>();
    mock.Expect(example => example.ExampleMethod()).Repeat.Times(ExpectedTimesToCall);

    for (var i = 0; i < ActualTimesToCall; i++) {
        mock.ExampleMethod();
    }

    // [?] This one passes
    mock.VerifyAllExpectations();
}

And yet when using AAA, we get the desired outcome (the following test fails):

[Test]
public void aaa_repeat_n_times_does_work_when_actual_greater_than_expected() {
    const Int32 ActualTimesToCall = 6;
    const Int32 ExpectedTimesToCall = 4;

    var mock = MockRepository.GenerateMock<IExample>();

    for (var i = 0; i < ActualTimesToCall; i++) {
        mock.ExampleMethod();
    }

    // This one fails (as expected)
    mock.AssertWasCalled(
        example => example.ExampleMethod(),
        options => options.Repeat.Times(ExpectedTimesToCall)
    );
}

Produces the message:

Rhino.Mocks.Exceptions.ExpectationViolationException: IExample.ExampleMethod();
Expected #4, Actual #6.

As expected.

The happens because of AbstractExpectation.CanAcceptCalls stops recording after range max has been reached, and so the actual number of calls recorded is never greater than the expected number:

// AbstractExpectation
public bool CanAcceptCalls
{
    get
    {
        //I don't bother to check for RepeatableOption.Never because
        //this is handled the method recorder
        if (repeatableOption == RepeatableOption.Any)
            return true;

        return expected.Max == null || actualCallsCount  > actualCallsCount )
            return false;

        if (Expected.Max==null)
            return true;

        // BJB: The following is always true
        return actualCallsCount <= expected.Max.Value;
    }
}

Solution?

I have been advised by someone on the Google group to use AAA syntax instead. And it is nicer to be sure — if a little less discoverable.

AAA and methods that return values

Expect is overloaded to handle return values — it supports Action<T> and Func<T, TReturnValue>. AssertWasCalled on the other hand does not support Func<T, TReturnValue>, so we have to suppress the return value manually in the function:

Stream mockStream = MockRepository.GenerateMock<Stream>();
mockStream.Expect(stream => stream.CanRead).
    Return(true).
    Repeat.Once();
...
mockStream.VerifyAllExpectations();

Becomes something like:

Stream mockStream = MockRepository.GenerateMock<Stream>();
...
mockStream.AssertWasCalled(
    stream => { var temp = stream.CanRead; },
    options => options.Return(true).Repeat.Once()
);

Written by benbiddington

23 June, 2009 at 08:50

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?

Written by benbiddington

31 October, 2008 at 09:33