Unit tests are not “unit” tests if they test things other than the System Under Test(SUT).
In order to test a SUT (the class to be tested), a developer must make sure that the class’s dependencies won’t interfere with its unit tests. Enter mocks and stubs.
Unit tests check on the behavior of units. Think of a class as being a unit. Classes, more often than not, have external dependencies. Tests for such classes should not use its real dependencies because if the dependencies have defects, the tests fail, even though the code inside the class may be perfectly fine.
Say you are not feeling well and go to the doctor to see what you have. The doctor looks at you and quickly says: “You have a problem*.”* How helpful would that be? Without knowing what kind of problem, it’s impossible for you to treat it, or to know whether it’s a serious problem or whether it’s something that will go away in a day or two.
Instead, the doctor should ask you a couple of questions, analyze the symptoms, decide on a series of exams appropriate to your condition, and then isolate the variables in order to diagnose more accurately what’s wrong with you, and finally, prescribe the best treatment. Once the treatment is finished, the doctor must conduct a few more tests to make sure everything’s all right.
Can you draw the parallel with software development here? How many times have users come to you to say: “Your application doesn’t work”? That sentence alone doesn’t give you enough information to prescribe any cure to your software. It’s necessary you run the application through a series of exams so you can pinpoint where the problem is, apply a fix, and run exams again to make sure you fixed the problem indeed. The exams must be isolated from one another (they mustn’t interfere with each other).
In this article I’ll look at how you can isolate your class being tested, also called system under test (I’ll only say SUT from here on), by using fake objects; you’ll see both how to create static fake objects, as well as how to use dynamic fake objects created by an isolation framework (also called mock framework).
The Scenario
This article uses a simple Windows Foundation Presentation (WPF) application as the basis for all samples. Figure 1 shows the main (and only) screen for this application.
The application keeps a list of videos. Each video has a title and a type (BluRay, DVD, or VHS). The user clicks the “Get Movies” button to retrieve the list, which can be filtered by video type. The user can then click any video in the list, causing the application to display the details for the movie at the bottom of the screen.
Granted, this is an overly simplistic application, but that’s good, for it allows you to concentrate on what you are ultimately trying to learn here, which is mocks and stubs.
One particular aspect of this application is that it’s implemented based on the Model-View-PresentationModel design pattern (or Model-View-ViewModel, which is pretty much the same thing).
This pattern promotes better separation of concerns, by keeping the part that the user sees (the “view”) as thin as possible; meaning that it should have as little code as possible. The main logic behind a view goes into a separate object: the “presentation model”. The presentation model object interacts with a “model” object, which provides the main data exposed by the view.
Listing 1 is the code behind the main view for the application; the VideosListView class, which inherits from the Window class and implements IVideosListView. You’ll notice there isn’t much to it. The class exposes a Model property of type IVideosListPresentationModel; as the name suggests, that’s the presentation model for this view (the view binds its UI controls to properties on this presentation model).
Other than that, the view simply raises a few events when important things happen, but doesn’t know what else to do with it (it’s not part of its responsibilities). The events raised are ShowVideoDetailsRequested (whenever the user selects a video on the list), and VideoListRequested (whenever the user requests the list of videos by clicking on “Get Videos”). All those members are defined in the IVideosListView interface.
Make sure to download the sample code for the application; in the article, I’ll only show the pieces of code relevant to the point being explained.
Your main task in this article is to write unit tests for the VideosListPresentationModel class; that’s the system under test (SUT).
Dealing with SUT’s Dependencies
The VideosListPresentationModel class has two dependencies: an object that implements IVideosListView, and an object that implements IVideosRepository. When writing tests for your SUT, you need to isolate those dependencies.
The first set of tests I want to write check to make sure the presentation model’s initial state has been properly set. There are three things to check for:
- The object’s View property should have a reference to the view object passed to its constructor.
- The Model property on the given view object should have a reference to the presentation model itself.
- No filter should be set by default, which you can check by inspecting the CurrentVideoTypeFilter property.
One of your first tasks when writing these tests is to instantiate the VideosListPresentationModel class. The snippet below shows the signature of the class’s constructor:
public VideosListPresentationModel(
IVideosListView view, IVideoRepository repository)
{
...
}
The constructor’s signature tells you that the class expects two dependencies to be injected into it: a view and a repository, of types IVideosListView and IVideoRepository, respectively. The parameters are typed to be interfaces so that you can use any object that implements those interfaces. Besides abiding by the Dependency Inversion Principle (by making the class depend on abstractions, instead of concretions), this approach also helps with testability, since you don’t need to pass in the real implementation of those dependencies when writing the unit tests.
You have already seen a class that implements IVideosListView earlier in this article: the VideosListView class. You may be thinking “Ah, so I could instantiate that class and pass it into the presentation model, couldn’t I?”
Yes, you could, but what if that class had some bugs that could interfere with your tests on the presentation model class? That’d be bad; unit tests shouldn’t fail because of defects of a class’s dependencies.
“But that VideosListView class seemed so simple; what could possibly go wrong?” The answer is: quite a few things.
For instance, there could be some problem with the XAML, preventing the class from being instantiated (a simple resource dictionary that can’t be found during run time would do it). Or maybe the window may use a third-party control which you only have a trial version for; a nag screen pops up whenever the window gets instantiated. You certainly don’t want a nag screen showing up when you run your tests.
Of course, there’s a lot more that could go wrong, but these are the examples that came to my mind first, since it happened to me recently!
What about that “repository” parameter? In this scenario, that object’s responsibility is to provide data to the presentation model (some people may jump at me saying that I should use a domain service instead of a repository, but bear with me; this is just a simple example).
The presentation model has no business knowing how the repository obtains the data (it could be going straight to a database, or using an Object-Relation Mapper framework, or reading the data from an XML file somewhere), and anything that goes wrong with the repository should not interfere with your tests on the presentation model.
Think about it: there are a lot of things that can go wrong when you try to retrieve data from a database, for instance. Besides, even if the test could get to the database, you’d be violating two best practices for unit tests: you’d be accessing an external resource, and you’d be causing the test to run slow (because connecting to a database and retrieving data is a slow process by nature).
By now you’ve established you can’t use the VideosListView class. So what do you do? Remember the constructor expects any object that implements the IVideosListView interface? You could pass in a fake object; a stub that looks like the real one, but doesn’t really do anything. The same solution applies to the repository.
Using Static Fake Objects
A static stub for IVideosListView is nothing more than a class statically defined by the developer. Such a class only has enough implementation code to satisfy the compiler:
public class StubView : IVideosListView
{
public IVideosListPresentationModel Model
{ get; set; }
public void Show()
{
}
public event
EventHandler<ShowVideoDetailsRequestedEventArgs>
ShowVideoDetailsRequested;
public event
EventHandler<VideoListRequestedEventArgs>
VideoListRequested;
}
Notice the Model property implemented as an auto-implemented property (therefore providing the minimal behavior for a property), the Show method doesn’t have any implementation code, and the two events, ShowVideoDetailsRequested and VideoListRequested, are declared but there’s nothing handling them.
A static stub is nothing more than a class statically defined by the developer.
The code below shows a similar stub class implementation for IVideoRepository:
public class StubRepository : IVideoRepository
{
public IEnumerable<Video> GetAllVideos()
{
return null;
}
public IEnumerable<Video>
GetAllVideosOfType(VideoType videoTypeFilter)
{
return null;
}
}
At this point you’re ready to start writing your tests. Remember the first tests you’re going to write check the expectations on the presentation model for its initial state. You start the test class as follows:
[TestClass]public class
VideosListPresentationModel_InitialState_Tests
{
private static VideosListPresentationModel PM;
private static StubView View;
private static StubRepository Repository;
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
View = new StubView();
Repository = new StubRepository();
PM = new VideosListPresentationModel(View,
Repository);
}
}
Notice that I use a FixtureSetup method (which runs before all tests within the test class are run) to instantiate both my stub classes as well as my presentation model.
Next, write the tests according to the expectations you had outlined earlier (the name of the test methods should remind you of what those expectations are):
[TestMethod]
public void Should_set_view_to_View_property()
{ Assert.AreEqual(View, PM.View); }
[TestMethod]
public void Should_set_model_for_given_view()
{ Assert.AreEqual(PM, View.Model); }
[TestMethod]
public void Should_default_to_NoFilter()
{
Assert.AreEqual("(No Filter)",
PM.CurrentVideoTypeFilter);
}
I run the tests, and see they all fail because I haven’t implemented those behaviors on my presentation model yet (as good Test-Driven Development practitioners do). Go on and implement the constructor on the presentation model class:
public VideosListPresentationModel(
IVideosListView view,
IVideoRepository repository)
{
m_Repository = repository;
View = view;
View.Model = this;
CurrentVideoTypeFilter = "(No Filter)";
}
You’ve implemented a few unit tests for the VideosListPresentationModel class, and you’re testing only the class’s implementation, without having to worry about the real implementation of its dependencies (in this case, the view and the repository). Move on to the next batch of tests.
When I’ve described the scenario of the sample application, I said that the user may get a list of videos using the user interface. I’ve mentioned that a user can accomplish this by selecting a video type as the filter, or “no filter”, and then clicking “Get Videos”.
When the user clicks “Get Videos” on the view, it raises the VideoListRequested event on it, passing the selected filter. The presentation model is then responsible for handling the event, populating its VideosList collection property, which the ListView control on the view is bound to. There are three expectations you need to test:
- The CurrentVideoTypeFilter property on the presentation model should be set to the filter requested by the user.
- If the user specifies “(No Filter)”, the VideosList property should end up containing all the videos available.
- If the user specifies a video type as the filter, the VideosList property should end up containing only videos that satisfy that filter.
Since this is a different context under which your presentation model should be tested, create a new test class for it; this makes the intent of your tests clearer, and prevents you from falling into the anti-pattern trap of creating one test class per SUT. Note however that this article is about mocks and stubs, and not about best practices on writing and organizing tests. To learn more about the latter, I recommend you take a look into the Behavior-Driven Development style of tests (check out Scott Belware’s article on the subject in the May/June 2008 issue of CODE Magazine).
The test class for this context would initially look pretty much like the one you created before, with the stubs and presentation model being instantiated in a FixtureSetup method. However, things start to get a little more complicated here. First, you need to find a way to raise the VideoListRequested event on the view (since that’s what happens when the user triggers that action on the UI). You certainly don’t want to pop up a UI, and then click a button for that. Instead, you can change your StubView class created previously, adding a method to it that can raise that event for you:
public void RaiseVideoListRequestedEvent(
string filter)
{
VideoListRequested(this,
new VideoListRequestedEventArgs(filter));
}
Next, you know that the presentation model must get the data somewhere, and you’ve established it uses the repository object for that. You must provide your StubRepository object with some sample data. Let’s add the following lines of code to that stub class:
private List<Video> m_ListOfVideos;
public void SetFakeData(List<Video> listOfVideos)
{
m_ListOfVideos = listOfVideos;
}
Nothing special going on there: the SetFakeData method allows you to feed some data into the repository so that it can give the data to the presentation model when requested. Remember that this is used just by your unit tests; normally the repository is likely to get that data from a database or something similar.
But wait, you had not implemented any of the querying methods on your StubRepository, so you must do that too:
public IEnumerable<Video> GetAllVideos()
{
return m_ListOfVideos;
}
public IEnumerable<Video> GetAllVideosOfType(
VideoType videoTypeFilter)
{
return m_ListOfVideos.Where(
v => v.VideoType == videoTypeFilter);
}
Very trivial: GetAllVideos simply returns the list you’ll send to SetFakeData, and GetAllVideosOfType will return the items that match the given criteria. You write as little code as possible.
With those changes in place, you can adjust the FixtureSetup in your new test class to the following:
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
// unchanged code elided
m_ListOfVideos = new List<Video>();
m_ListOfVideos.Add(new Video {Title = "Video 1",
VideoType = VideoType.BluRay });
m_ListOfVideos.Add(new Video {Title = "Video 2",
VideoType = VideoType.Dvd });
Repository.SetFakeData(m_ListOfVideos);
}
Note you create some arbitrary set of test data, and feed it to the stub repository by means of the SetFakeData method.
Now you can write the tests. The first test checks whether the CurrentVideoTypeFilter property gets set to the filter passed to the event:
[TestMethod]
public void
Should_set_current_filter_to_requested_filter()
{
string filter = VideoType.Dvd.ToString();
Assert.AreNotEqual(filter,
PM.CurrentVideoTypeFilter);
View.RaiseVideoListRequestedEvent(filter);
Assert.AreEqual(filter,
PM.CurrentVideoTypeFilter);
}
Next, you test to see if the VideosList gets populated with all the videos when the event gets raised with filter set to “no filter”:
[TestMethod]
public void
Should_retrieve_all_videos_if_no_filter_spec()
{
View.RaiseVideoListRequestedEvent(
"(No Filter)");
Assert.AreEqual(m_ListOfVideos.Count,
PM.VideosList.Count);
}
And finally, test to make sure that VideosList gets populated with only the videos that satisfy the filter requested:
[TestMethod]
public void
Should_retrieve_only_videos_for_specified_filter()
{
View.RaiseVideoListRequestedEvent(
VideoType.BluRay.ToString());
Assert.AreEqual(1, PM.VideosList.Count);
Assert.AreEqual("Video 1",
PM.VideosList[0].Title);
}
It’d be great to be able to create fake objects dynamically as you need them, and that’s where a mock framework comes in handy.
Listing 2 contains the parts of VideosListPresentationModel that are relevant to the last three tests you’ve just created. I’ve hooked up the event handler for the VideoListRequested event in the class’s constructor. The method that handles the event updates the CurrentVideoTypeFilter property, and calls either GetAllVideos or GetAllVideosOfType methods on the repository, depending on whether the user specified a filter; the code puts the result returned by either method in the VideosList property.
Considerations on Static Fake Objects
For the six tests you’ve written so far, you’ve created two static fake classes: StubView and StubRepository. You should recall that for the first three tests (the ones validating the initial state behavior of the presentation model), you created the fake classes with the bare minimum implementation. However, for the second set of tests (the ones that validate the list retrieval behavior) you’ve had to make changes to those fake classes, so to fit the context for the tests.
What if the changes you’ve made to support the second set of tests had broken the first set of tests? That wouldn’t be good. And what if in order to write the remaining tests for this presentation model you have to make even more changes to the fake classes? You could end up adding if-blocks, switch-blocks, and things of that sort, in order to support the different contexts of different tests. That would turn your fake classes into a big mess, and you don’t want that.
One possibility would be to create one set of fake classes for each specific context required by your tests, which could also turn into a maintenance nightmare.
Wouldn’t it be nice to just use some sort of framework where you say “give me an object that implements this interface and whenever somebody calls this specific method, return this result”? In other words, it’d be great to be able to create fake objects dynamically as you need them, and that’s where a mock framework comes in handy.
Using Dynamic Fake Objects
There are several frameworks out there (often referred to as “mock frameworks”), both commercial and free, that create dynamic fake objects for you. The more popular free ones are Rhino Mocks and MOQ, whereas TypeMock a popular commercial one. Table 1 lists where you can go to find them. Those frameworks provide similar kinds of features, but they are implemented in a different way. I am going to use Rhino Mocks in this article.
You are going to rewrite the tests you wrote so far, but using Rhino Mocks this time around. You can go ahead and get rid of both the StubView and StubRepository classes.
Go back to the VideosListPresentationModel_InitialStates_Tests test class and make a few changes to it. In that class you had fields to store references to your stub view and repository objects:
private static StubView View;
private static StubRepository Repository;
Since you don’t have those fake classes any more, you need to change the type of those fields. Change them to their respective interface types:
private static IVideosListView View;
private static IVideoRepository Repository;
Next, you need to change the code where you were assigning instances of those fake classes to those fields. Use Rhino Mock’s MockRepository’s GenerateStub method to create dynamic mocks for those interfaces. The MockRepository class exists under the Rhino.Mocks namespace:
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
View =
MockRepository.GenerateStub<IVideosListView>();
Repository =
MockRepository.GenerateStub<IVideoRepository>();
PM = new VideosListPresentationModel(View,
Repository);
}
Rhino creates a dynamic class during run time; it creates the class providing a minimal implementation (very similar to the classes you had created before, except that you don’t need to maintain individual classes yourself).
Those are the only changes you need here. You should be able to run the tests and see they all pass.
Now off to the other three tests you wrote; the ones testing the videos list retrieval behavior. Hopefully you’ll remember that you had needed to add more code to your fake classes in order to support those tests. First, you had to add a method to the StubView class so you could raise the VideoListRequested event on the view:
public void RaiseVideoListRequestedEvent(
string filter)
{
VideoListRequested(this,
new VideoListRequestedEventArgs(filter));
}
Then you added a SetFakeData method to the StubRepository class so you could feed it some test data:
private List<Video> m_ListOfVideos;
public void SetFakeData(List<Video> listOfVideos)
{
m_ListOfVideos = listOfVideos;
}
You’ve also had to implement the methods on the StubRepository class that retrieve the videos lists:
public IEnumerable<Video> GetAllVideos()
{
return m_ListOfVideos;
}
public IEnumerable<Video> GetAllVideosOfType(
VideoType videoTypeFilter)
{
return m_ListOfVideos.Where(
v => v.VideoType == videoTypeFilter);
}
Let’s rewrite these tests, leveraging the possibilities Rhino Mocks gives you.
As you’ve done before, get rid of the references to both StubView and StubRepository, and replace those with references to their respective interfaces. You use MockRepository.GenerateStub<interface>() like you did before. Nothing new so far.
Proceed with removing the call to SetFakeData, since you don’t have an object with that method anymore:
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
// unchanged code elided
// This is no longer necessary!
// Repository.SetFakeData(m_ListOfVideos);
}
The Should_set_current_filter_to_requested_filter test requires a simple change; instead of calling a RaiseVideoListRequestedEvent method, you raise the event by using a feature of Rhino Mocks that allows you to raise events on an object:
[TestMethod]public void
Should_set_current_filter_to_requested_filter()
{
string filter = VideoType.Dvd.ToString();
Assert.AreNotEqual(filter,
PM.CurrentVideoTypeFilter);
View.GetEventRaiser(x =>
x.VideoListRequested += null)
.Raise(null,
new VideoListRequestedEventArgs(filter));
Assert.AreEqual(filter,
PM.CurrentVideoTypeFilter);
}
The call to View.GetEventRaiser looks weird because I had to reformat the code to fit the magazine’s layout, but that line of execution will hopefully make sense once I’ve explained it.
By importing the Rhino.Mocks namespace to the current source file, you get several extension methods, free of charge, that help you when writing your tests. One of these methods is the GetEventRaiser method. That method takes in a lambda expression containing the expression used to wire up an event:
x => x.VideoListRequested += null
Assign null to the event because you don’t really need to handle that event here. GetEventRaiser returns an IEventRaiser object, which in turn has a Raise method. You then call Raise, passing in whatever parameters are necessary when the event is raised; in the case of the VideoListRequested event, it expects a sender object, as well as a VideoListRequestedEventArgs object:
.Raise(null,
new VideoListRequestedEventArgs(filter));
You’re passing null as the sender because that parameter is irrelevant in this case.
Off to the Should_retrieve_all_videos_if_no_filter_spec (specified) test method. That method raises the VideoListRequested event, passing in “(No Filter)” as the filter, and then checks whether you get the correct number of videos back. The one change you know you need here is to use GetEventRaiser/Raise to raise the event, like you just did in the previous test.
The other thing the test needs is to provide the repository some test data because now you don’t have that SetFakeData method any more, and the dynamic stub doesn’t have any data by default.
Under this scenario (the user requests a list with no filter applied), you know that the presentation model is going to call a GetAllVideos method on the repository. So what you need to do is to “stub out” that method call, making it return whatever it is that you need to satisfy the expected context of your test. The dynamic stub gives you a Stub method that allows you to do just that:
[TestMethod]public void
Should_retrieve_all_videos_if_no_filter_spec()
{
Repository.Stub(x =>
x.GetAllVideos())
.Return(m_ListOfVideos);
// remaining code elided
}
Notice the call to the Stub method takes in a lambda expression containing your expected call to GetAllVideos, and the call to the Return method takes in the object you want returned whenever that call to GetAllVideos happens. In order words, you could read that line of execution as: “Whenever GetAllVideos is called on the repository, return m_ListOfVideos*.”*
You’re done with that test, so move on to the other one: Should_retrieve_only_videos_for_specified_filter. In that test you were raising the VideoListRequested event, passing in a specific filter (VideoType.BluRay). The changes you have to make to this test are similar to the changes you’ve made to the previous one: use GetEventRaiser/Raise to raise the event, and before that, stub out the call to the method on the repository that you expect the presentation model to make (in this case, GetAllVideosOfType), and return the expected test data:
VideoType filter = VideoType.BluRay;
IEnumerable<Video> filteredList =
m_ListOfVideos.Where(v => v.VideoType == filter);
Repository.Stub(x =>
x.GetAllVideosOfType(filter))
.Return(filteredList);
View.GetEventRaiser(x =>
x.VideoListRequested += null)
.Raise(null, new
VideoListRequestedEventArgs(filter.ToString()));
State-based and Interaction-based Tests
At this point you may be thinking: “I thought this article was about **mocks **and stubs, but so far I’ve only seen stubs!” So it’s time you have a look at mocks.
Up to this point, your tests can be considered “state-based” tests: you act upon your system under test, and then you check its state to make sure it matches your expectations. In your first batch of tests, you were checking the state of your presentation model after it had been instantiated, for instance: Does it have references set to the appropriate objects? Or: Does it have some properties set to some specific defaults? The second batch of tests checked the state of the presentation model, more specifically the state of its VideosList property, to make sure the list gets populated properly after the presentation model has handled an event raised by the view. Stubs are the type of fake objects that help you with state-based testing. They are either filled with values to be read by the SUT to perform its duties, or they have values set on them by the SUT, and then checked by the test.
There are other situations when state-based tests aren’t possible, or aren’t easy to write (for instance, there may not be a state to check for). This type of situation comes up when the SUT has dependencies, and what you need tested is the interaction of the SUT with its dependencies. When this is the case, you can resort to interaction-based tests. Mocks are the type of fake objects that help you with interaction-based testing. They act as sort of spies, watching expectations set by the test on the mock, and then reporting these expectations back to the test.
Interaction-based Tests Using Static Fake Objects
In your sample application, the VideosListPresentationModel has the responsibility to show its view when requested. That’s done by calling its ShowView method on the presentation model. The ShowView method shows the view by sending a message to it; that is, calling the view’s Show method. This is the implementation of the ShowView method in the VideosListPresentationModel class:
public void ShowView()
{
View.Show();
}
The test for that behavior has to check for the interaction between the presentation model and its view. In order to write such a test using a static mock object, you need to write some code so that whenever methods get called you flip a Boolean field to indicate that the message has been received; the test can then check the value of that field to see whether the expectation has been met.
Start by creating a static mock class that implements your IVideosListView interface:
public class MockView : IVideosListView
{
public bool ShowWasCalled;
public void Show()
{
ShowWasCalled = true;
}
// other members code elided
}
The important piece there is that you define a ShowWasCalled Boolean property, which gets set to true by the Show method whenever that method gets called.
Your test class for that behavior looks pretty much like the ones you’ve created earlier in this article when you were using static stub classes, except that now you instantiate the MockView class, as opposed to the StubView class:
Stubs are the type of fake objects that help you with state-based testing.
[TestClass]public class
VideosListPresentationModel_ViewDisplay_Tests
{
private static VideosListPresentationModel PM;
private static MockView View;
private static StubRepository Repository;
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
View = new MockView();
Repository = new StubRepository();
PM = new VideosListPresentationModel(View,
Repository);
}
}
The following snippet shows the test method for that expected behavior:
[TestMethod]
public void ShowView_should_display_the_view()
{
PM.ShowView();
Assert.IsTrue(View.ShowWasCalled);
}
Not much there: you act on the presentation model by calling its ShowView method, and you check the ShowWasCalled property on the “mock” View to make sure the message was sent to that object, therefore, validating the interaction between the two objects.
So how would you write an interaction-based test using dynamic mocks?
Interaction-based Tests Using Dynamic Fake Objects
Let’s go ahead and change things around so you can rewrite your test using dynamic fake objects (which means you can get rid of that MockView class you created in the previous section). The main aspects of your test class using dynamic fake objects are highlighted in the code snippet below:
private static VideosListPresentationModel PM;
private static IVideosListView View;
private static IVideoRepository Repository;
[ClassInitialize()]
public static void FixtureSetup(TestContext tc)
{
View =
MockRepository.GenerateMock<IVideosListView>();
Repository =
MockRepository.GenerateStub<IVideoRepository>();
PM = new VideosListPresentationModel(View,
Repository);
}
Type both your View and Repository fields to their respective interfaces. The Repository field gets an instance of a stub generated by Rhino Mocks; whereas, the View field gets an instance of a mock generated by Rhino Mocks. I’ll explain what the difference is between a stub and a mock shortly.
Next, let’s have a look at what your test method should look like now:
[TestMethod]
public void ShowView_should_display_the_view()
{
PM.ShowView();
View.AssertWasCalled(v => v.Show());
}
AssertWasCalled is another one of those nice extension methods that are brought in when you import the Rhino.Mocks namespace. You call that method on the View to assert that a given method was called on it; in this case, the Show method. There is no need to create a separate class manually, create a Boolean field, and then set that field within the method you expected to be called! Rhino Mocks takes care of inspecting the object to make sure the expected method was called.
Mocks are the type of fake objects that help you with interaction-based testing.
So what happens if you break the ShowView method, by removing the call to View.Show(). The test would then fail, and Rhino Mocks would give you the following error message:
TestCase
'VideosListPresentationModel_ViewDisplay_Tests.
ShowView_should_display_the_view'
failed:
Rhino.Mocks.Exceptions.ExpectationViolation
Exception: IVideosListView.Show(); Expected #1,
Actual #0.
In other words, the test failed because you expected one call to IVideosListView.Show(), but didn’t get any.
GenerateMock versus GenerateStub
So what’s the difference between the GenerateMock and GenerateStub methods? The dynamic objects created by both methods are very similar. The main difference is that mock objects can cause a test to fail in case expectations set on it aren’t met. A stub, on the other hand, won’t cause a test to fail in case expectations set on it aren’t met.
You can learn more about these subtle differences reading the documentation on Rhino Mocks. Also make sure to read Martin Fowler’s “Mocks Aren’t Stubs” article: http://martinfowler.com/articles/mocksArentStubs.html.
Should I Use Dynamic Fake Objects Exclusively?
Dynamic fake objects are not silver bullets. They certainly help in many scenarios, but may not be very helpful in others. There are cases where configuring the dynamic mock is so hard and/or complex that it’s better to just create a simple static fake object for it. It’s up to the developer to analyze the situation and decide what technique will produce a test that is easier to write, understand, and maintain.
Also, there are situations where a mock framework may have limitations that can rule out its use. For instance, Rhino Mock can only mock virtual members, and cannot mock sealed classes. Many developers would argue that members should always be virtual, and mocking sealed classes shouldn’t be necessary if classes have been designed properly, but you may be in a situation where you just can’t afford the time or money to make changes to your design to make your classes more testable.
TypeMock, on the other hand, can mock pretty much everything: sealed classes, private and non-virtual members, etc. That’s definitely useful when writing tests for a legacy code base that hasn’t been designed with testability in mind and fixing the design and implementation is out of question, but it may also spoil you and lead you to write sloppy code.
I really don’t want to dive into that discussion because a lot has already been said about it on the Web. I’ll leave it up to you, the reader, to go do some research and see what you think. I just wanted to briefly mention these things so you are aware of their existence.
Summing Up
This article covered the isolation of dependencies when writing unit tests by using fake objects. By isolating those dependencies you end up with unit tests that become more informative in case things go wrong, because you’re more likely to be tracking a bug in your system under test, as opposed to tracking a bug that may be coming from the SUT’s dependencies. Fake objects also help the unit test being really a “unit” test, causing it to run faster and independent of outside resources such as files on disk, databases, Web services, etc.
Mock frameworks help you with keeping your code base cleaner, preventing you from creating and maintaining several individual classes for static fake objects.
In this article you’ve covered some basic scenarios, the main differences between static and dynamic fake objects, as well as state-based and interaction-based tests. You’ve also covered a little of how to use Rhino Mocks for dynamic fake objects. Rhino Mocks deserves an entire article solely dedicated to it, showing how to leverage the framework when writing tests for more complex behaviors.
Listing 1: Code behind VideosListView class.
public partial class VideosListView : Window, IVideosListView{
public IVideosListPresentationModel Model
{
get
{
return this.DataContext as IVideosListPresentationModel;
}
set { this.DataContext = value; }
}
private void listView_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
ShowVideoDetailsRequested(this,
new OpenVideoRequestedEventArgs(
listView.SelectedItem as Video));
}
private void getVideosButton_Click(object sender,
RoutedEventArgs e)
{
var selectedType = videoTypeComboBox.SelectedItem.ToString();
VideoListRequested(this,
new VideoListRequestedEventArgs(selectedType));
}
public event EventHandler<ShowVideoDetailsRequestedEventArgs>
ShowVideoDetailsRequested = delegate { };
public event EventHandler<VideoListRequestedEventArgs>
VideoListRequested = delegate { };
}
Listing 2: Implementation of list retrieval on VideosListPresentationModel.
public class VideosListPresentationModel :
IVideosListPresentationModel, INotifyPropertyChanged
{
private ObservableCollection<Video> m_VideosList;
public ObservableCollection<Video> VideosList
{
get { return m_VideosList; }
set
{
m_VideosList = value;
PropertyChanged(this,
new PropertyChangedEventArgs("VideosList"));
}
}
public VideosListPresentationModel(IVideosListView view,
IVideoRepository repository)
{
m_Repository = repository;
View = view;
View.Model = this;
View.VideoListRequested += View_VideoListRequested;
CurrentVideoTypeFilter = "(No Filter)";
}
void View_VideoListRequested(object sender,
VideoListRequestedEventArgs e)
{
CurrentVideoTypeFilter = e.VideoTypeFilter;
if (CurrentVideoTypeFilter == "(No Filter)")
{
UpdateVideoListWith(m_Repository.GetAllVideos());
}
else
{
var filter = (VideoType)Enum.Parse(typeof(VideoType),
CurrentVideoTypeFilter);
UpdateVideoListWith(m_Repository.GetAllVideosOfType(filter));
}
}
private void UpdateVideoListWith(IEnumerable<Video> videos)
{
VideosList = new ObservableCollection<Video>(videos);
}
public event PropertyChangedEventHandler PropertyChanged =
delegate { };
}
Table 1: Some of the most popular Mock Frameworks.
Mock Framework | URL |
---|---|
Rhino Mocks | http://ayende.com/projects/rhino-mocks.aspx |
MOQ | http://code.google.com/p/moq/ |
TypeMock | http://www.typemock.com |