Rhino Mocks Boo Macros

Downloads

Source Code
Compiled DLL

Introduction

This is a .NET library of syntactic macros for the Boo programming language. The macros work with the Rhino Mocks mock object library. They ease setting up expectations on mock objects. Instead of long method chaining, you can use normal Boo syntax.

Here is an example of setting up an expectation of a method call.

def Example():
    record mocks:
        foo as IFoo = mocks.CreateMock(IFoo)
        expect foo.Dog(int, x as string, y as int):
            x [ Is.NotNull() ]
            y [ Is.GreaterThan(0) & Is.LessThan(10) ]
            return 42.0
    verify mocks:
        foo.Dog(0, "hello", 5)

The equivalent regular Rhino Mocks code would be similar to:

def Example():
    mocks = MockRepository()
    foo as IFoo = mocks.CreateMock(IFoo)
    Expect.Call(foo.Dog(0, null, 0))
        .Constraints(Is.Anything(), Is.NotNull(), Is.GreaterThan(0) & Is.LessThan(10) )
        .Return(42.0)
    mocks.ReplayAll()
    foo.Dog(0, "hello", 5)
    mocks.VerifyAll()

Replacing long method chaining with a macro block makes the intention much clearer. In addition, the record and verify macros reduce the visual noise by removing the boilerplate Rhino Mocks replay and verify calls.

Macro Usage

There are nine expectation macros. These are from the three modes of expectation (allow, expect and disallow) and three kinds of mock members supported (methods, property getters and property setters).

    Mock Member
    Method Property Getter Property Setter
Expectation Allow allow allow_get allow_set
Expect expect expect_get expect_set
Disallow disallow disallow_get disallow_set

Allow

Use an allow macro when you want to specify that a method or property can be called zero or more times.

Expect

Use an expect macro when you want to ensure that a method or property is called a fixed number of times (by default, once).

Disallow

Use a disallow macro when you want to prevent a method or property being called. This is useful when using dynamic mocks.

Parameters and Constraints

Syntax:

allow mockObject.Method([parameters]):
    [options]

The parameter list defines the signature of the method (avoiding ambiguity with overloaded methods). If you do not want to constrain a parameter, you need only give its type.

allow mockObject.Method(int)

To constrain a parameter, you must have a name for it. The following snippet demonstrates the use of parameter constraints.

allow mockObject.Method(x as int):
    x [ Is.Equal(42) ]

The syntax for a constraint is:

parameter-name [ Rhino.Mocks.Constraints.AbstractConstraint ]

You can use any subclass of AbstractConstraint, such as those built into Rhino Mocks, or your own custom constraint objects. Rhino Mocks also supports composition of constraints using the bitwise-and and bitwise-or operator overloads.

allow mockObject.Method(x as int):
    x [ Is.GreaterThan(0) & Is.LessThan(10) ]

You do not have to specify constraints for all parameters. You need only name the parameters you wish to constrain. For example:

allow mockObject.Method(x as int, string):
    x [ Is.Equal(42) ]

The nameless second parameter serves only to resolve the method signature and allow the macro to create a correct default value. (Unconstrained parameters implicitly generate an Is.Anything() constraint for Rhino Mocks.)

When specifying a property setter you can constrain the implicit value parameter.

allow_set mockObject.Name:
    value [ Text.Contains(“foo”) ]

Return Values

If a member has a return type (a method or property getter) then you can specify the value to return. Omitting the return value will cause the macro to return a default value based on the member’s type.

Example of setting return value:

allow mockObject.Method():
    return 42

A return statement transforms into a call to Rhino Mocks IMethodOptions.Return(value).

Raising Exception

To make a mock member raise an exception, use the following syntax.

allow mockObject.Method()
    raise Exception()

You can raise any type of exception – just like the normal Boo raise statement.

Note that having both a return and raise statement is invalid.

A raise statement transforms into a call to Rhino Mocks IMethodOptions.Throw(value).

Repeats

When specifying an expectation, you can set the number of repeated calls allowed. (This does not apply to allow and disallow macros.)

Use either,

expect mockObject.Method():
    repeat(value)

or,

expect mockObject.Method():
    repeat(min, max)

The first form specifies the exact number of repetitions expected. The second specifies that the number of repetitions must fall within a given range.

A repeat will transform into a call to Rhino Mocks IMethodOptions.Repeat(value) or IMethodOptions.Repeat(min, max).

Copyright © 2006 Andrew Davey

Blog http://blogs.warwick.ac.uk/andrewdavey/
Email andrew@equin.co.uk