barbarian meets coding

WebDev, UX & a Pinch of Fantasy

Rhino Mocks

Rhino Mocks is an open source .NET mocking framework created by Oren Eini. Rhino Mocks source code is hosted at GitHub

Rhino Mocks Fundamentals

Install Rhino Mocks

Grab it from Rhino Mocks website or via NuGet:

1
PM> Install-Package RhinoMocks

Mocks in Rhino Mocks

You can easily create mocks in Rhino Mocks by using a MockingRepository as illustrated below:

1
var emailServiceMock = MockRepository.GenerateMock<IEmailService>();

And assert expectations like:

1
2
3
4
5
var emailServiceMock = MockRepository.GenerateMock<IEmailService>();
// Assert that a method was called
emailServiceMock.AssertWasCalled(e => e.sendReminder(user));
// Assert that a property was set
emailServiceMock.AssertWasCalled(e => e.StmpPort = 25);

Stubs in Rhino Mocks

Rhino Mocks also provides support for creating stubs:

1
var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>();

And to configure them as detailed below:

1
2
3
4
5
6
7
8
var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>();
// stub a method call
userRepository.Stub(r => r.GetUserById(user.Id)).Return(user);
userRepository.Stub(r => r.GetUser(Arg<User>.Is.Anything)).Return(user);
userRepository.Stub(r => r.UserExists(user)).Return(false);
// specifying property values
userRepository.Count = 0; // only works if property is not read only
userRepository.Stub(r => r.Count).Return(0); // for read-only properties

As a side note, you can also use GenerateMock and use the generated object as a stub. (At the end of the day, a fake object becomes a stub or a mock depending on the way you use it in a test).

A Note About Rhino Mocks Constraints

Rhino Mocks Constraints give you a lot of flexibility in your test setups and assertions by providing a way to:

  1. setup method arguments to match a criteria
  2. verify that method arguments match a criteria

For instance:

1
2
3
4
// Arg<User>.Is.Anything is a constraint
mockUserRepository.AssertWasCalled(x => x.Save(Arg<User>.Is.Anything));
mockUserRepository.AssertWasCalled(x => x.Save(Arg<User>.Is.NotNull));
mockUserRepository.AssertWasCalled(x => x.Save(Arg<User>.))

It comes in any of these flavors: Is, Matches, List and Text.

The Is Constraint

Is allows you to set up simple and common constraints.

1
2
3
4
5
6
7
8
Arg<T>.Is.Anything() // matches anything
Arg<T>.Is.Equal(something) // matches by equality
Arg<T>.Is.Null() // matches if null
Arg<T>.Is.NotNull() // matches if not null
Arg<T>.Is.Same(something)
Arg<T>.Is.NotSame(something)
Arg<T>.Is.GreatherThan(10)
Arg<T>.Is.LessThan(10)

The Matches Constraint

Matches allows you to use a arbitrary predicates to set a constraint:

1
2
Arg<User>.Matches(u => u.Id == user.id) // match by user id
Arg<User>.Matches(u => u.FirstName == firstName && u.LastName == lastName) // match by user firstName and lastName

The List Constraint

List allows you to set up constraints based on collections.

1
2
3
4
Arg<List<User>>.List.ContainsAll(students)
Arg<List<User>>.List.Equal(students)
Arg<List<User>>.List.Count(Rhino.Mocks.Constraints.Is.Equal(3))
Arg<List<User>>.List.IsIn(aStudent)

The Text Constraint

Text allows you to set up constraints based on string matchings.

1
2
3
4
Arg<string>.Matches(Rhino.Mocks.Constraints.Text.Contains("hello"))
Arg<string>.Matches(Rhino.Mocks.Constraints.Text.StartsWith("hello"))
Arg<string>.Matches(Rhino.Mocks.Constraints.Text.EndsWith("world"))
Arg<string>.Matches(Rhino.Mocks.Constraints.Text.Like("hello.*")) // use regex

Constraints for Out and Ref Parameters

1
2
3
4
// Out parameters
userRepository.Stub(r => r.Get(out Arg<User>.Out(new User()).Dummy))
// Ref parameters
userRepository.Stub(r => r.Save(ref Arg<User>.Ref(constraint: Rhino.Mocks.Constraints.Is.Anything(), returnValue: new User())))

Creating Custom Constraints

Creating custom constraints in Rhino Mocks is as easy as creating a new implementation of AbstractConstraint, the abstract base class for all constraints in Rhino Mocks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Constraint implementation
public class UserConstraint : AbstractConstraint
{
    public UserConstraint(User expectedUser){...}
    // The Eval method is called when the constraint is evaluated 
    public override bool Eval(object actual){...}
    // The Message property returns a message
    // to display when the constraint evaluates to false
    public override string Message {get {...}}
    ...
}
...
// Constraint use
Arg<User>.Matches(new UserConstraint(expectedUser));

Resources

Comments