In the first part of my introduction course to Rhino Mocks I will explain what stub objects are, how you can create stub objects and how you can configure their behaviour. First of all let me explain what stub objects are: a stub is typically used as a placeholder; they do not generate any expectations. However you can use the properties on them and configure method results.

In this example I will show you how to create a message dispatcher which can send messages using multiple sender implementations. Image that you have no idea how to implement the different senders, but you know the contract, here it is:

/// <summary>Defines the public interface for the senders.</summary>
public interface ISender
{
	/// <summary>Sends the message.</summary>
	/// <param name="msg">The message to send.</param>
	/// <returns>Returns true when the message was sent, otherwise false.</returns>
	bool	Send(object msg);
	/// <summary>Gets the is ready flag.</summary>
	bool	IsReady	{get;}
}

As you can see the contract is extremely simple. The IsReady flag indicates whether the sender implementation is ready (true) to send a message or not (false). The Send(msg) function implements the actual sending of the message.

The message dispatcher class is very simple as well. Here is its interface:

/// <summary>Implements the message dispatcher.</summary>
public class MessageDispatcher: object
{
	/// <summary>Constructs an message dispatcher instance with the specified senders.</summary>
	/// <param name="senders">The senders.</param>
	public MessageDispatcher(params ISender[] senders): base() {}
	/// <summary>Dispatches the specified message to all the able senders.</summary>
	/// <param name="msg">The message which to send.</param>
	/// <returns>Returns the number of sent messages.</returns>
	public int	Dispatch(object msg){}
	private ISender[]	senders;
}

The constructor of the MessageDispatcher class takes an ISender[] array which contains all the senders through which messages are sent. The Dispatch(msg) function sends the message through each ISender instance which is ready to send a message and returns the count of the successful sent messages.

Now that we have a class to test, namely the MessageDispatcher, letâ??s go write some unit-tests. The first step is to create the mock repository which is main component of the Rhino Mocks framework; it is responsible for creating mocks, stubs and managing the recorder state. It is very easy to create the mock repository:

MockRepository mockRepository = new MockRepository();

I generally create the repository in the setup phase of the unit test. You get code that looks something like this:

[SetUp()]
public void	Init()
{
	// create the mock repository
	this.mockRepository = new MockRepository();
}

Now that we have the infrastructure in place, letâ??s create a unit-test for the constructor. Remember that the constructor takes an array of ISender? Guess what, I donâ??t have a class implementing ISender so I have to mock it. To do that we use the Stub() function on the MockRepository which creates a stub of the desired object.

The test looks something like this:

[Test()]
public void	Constructor()
{
	// create
	ISender stubSender		= this.mockRepository.Stub<isender>();
	MessageDispatcher dispatcher	= new MessageDispatcher(stubSender);

	// perform tests
}</isender>

As far as the MessageDispatcher class is concerned stubSender is a perfectly normal implementation of the ISender interface like any other. Now that you know how to create stubs let go to the more advanced capabilities of stubs like configuring properties and functions.

Record and Playback

Before we go to those advanced capabilities, let me explain first what the record/playback model is. The Rhino Mocks framework has basically two operation modes: record and playback. There are several ways in which you can manipulate the modes; in this article I will use the strict method.

In the record mode you â??recordâ?? what is supposed to happen. For instance you want to make sure that a method is called with the appropriate arguments. This is done through calling the methods on the mocked objects and set expectations on the method call. You go to record mode by using the following code:

// move to record mode
using (mockRepository.Record())
{
	// set exepectations
}

In the playback mode you do the actual normal stuff. At the end of the playback mode the Rhino Mocks framework checks if all the expectations, set in the record mode, are met. You go to playback mode by using the following code:

// move to playback mode
using (mockRepository.Playback())
{
	// perform normal operation
}

Let’s move on the more interesting stuff.

Configuring Stub Object Behavior

In this section I will explain how you can configure the behavior of the created stub objects. Rhino Mocks framework contains a set of utilities which let you alter the behavior of stubbed objects, for example: configure the return results for functions.

Properties

You might need a particular property to return a predetermined value. You can accomplish this by using the SetupResult class which is part of the Rhino Mocks framework. Remember you must be record mode in order to configure the stub’s property. You can use the following line of code to configure return values of properties:

// stubSender.IsReady will always return true
SetupResult.For(stubSender.IsReady).Return(true);

Functions

You can configure the return result for the mocked object functions. You can use the SetupResult class again to achieve the desired result. Remember you must be record mode in order to configure the stub’s function return results. You can use the following line of code to configure return result of functions:

// stubSender.Send(msg) will always return true regardless of the arguments passed
SetupResult.For(stubSender.Send(null)).IgnoreArguments().Return(true);

You can even easily return different results based on the arguments which are passed to the mocked object’s functions:

// stubSender.Send(msg) will always return false when argument notSendableMsg is passed
SetupResult.For(stubSender.Send(notSendableMsg)).Return(false);

// stubSender.Send(msg) will always return true when argument sendableMsg is passed
SetupResult.For(stubSender.Send(sendableMsg)).Return(true);

Project

I uploaded the project on which this article is based to the weblog and I encourage you to download it and play around with it. Click here to download the project.

Conclusion

That is it for now; we covered the creation of stub objects and the modification of its behaviour. I hope you gained some insight into the working of the Rhino Mocks framework and that you understand how usable stub objects are when testing.

I only showed you some of the basics of the Rhino Mocks framework and in the next part I will cover the different types of mock objects and I will show you how to set expectations on method calls.

If you have any questions, comments or suggestions, please post them here. Last but not least: Thank you for taking the time to read my article, I hope you liked it.

Be Sociable, Share!