Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Isolating Dependencies in Tests Using Mocks and Stubs : Page 3

Unit tests are not "unit" tests if they test things other than the System Under Test (SUT).


advertisement

Getting Sample Data

Next, you know that the presentation model must get the data somewhere, and you've established it uses the repository object for that. Therefore, you must provide your StubRepository object with some sample data. 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 lets you feed some data into the repository so it can give the data to the presentation model when requested. Remember that this is used only by your unit tests; normally the repository is likely to get that data from a database or something similar.

But wait, you have not implemented any 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); }

As you can see, the querying methods are trivial: GetAllVideos simply returns the list you'll send to SetFakeData, and GetAllVideosOfType will return 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 as follows:

[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 that you're simply creating some arbitrary set of test data, and feeding that to the stub repository using 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 property 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); }

Finally, test to make sure that VideosList gets populated with only the videos that satisfy the requested filter:

[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 1 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 handler updates the CurrentVideoTypeFilter property, and calls either GetAllVideos or GetAllVideosOfType methods on the repository, depending on whether the user specified a filter; in either case, the code returned results 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, 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, or more things of that sort to support the different contexts for different tests. That would turn your fake classes into a big mess, and you don't want that.

Another 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 when you can simply request an object that implements an interface, and specify the results to return for any specific method? In other words, it'd be great to be able to create fake objects dynamically as you need them. That's where a mock framework comes in handy.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date