Vadim's Weblog

Never stop learning.

Tutorial to TDD using Rhino Mocks and SystemWrapper.

Posted by Vadim on December 4, 2008

In this post I want to introduce to SystemWrapper and demonstrate how it works with Rhino Mocks.
 
SystemWrapper is just a wrapper to .NET system resources like FileInfo, DirectoryInfo, Assembly, … .
 

Why do we need SystemWrapper?

 
Let assume that you’re writing code that creates a directory.  In your unit test you don’t want to create a directory you just want to know that Directory.CreateDirectory(@”C:\MyDir”) was called.  You cannot mock Directory because it’s a static class.  By wrapping Directory in SystemWrapper we can mock Directory object.  Whenever you use Directory, just use IDirectoryWrap interface instead.
 
 

TDD example with Rhino Mocks and SystemWrapper.

 

Goal:

Create a method that tries to create a directory.  If the directory already exists, don’t create it and return false; otherwise, create directory and return true.  Sounds simple enough.
 

Requirements:

Any unit testing framework of your choice.  (I’m using MbUnit v3 which is part of Gallio).
This example is taking advantage of .NET 3.5.  Let me know if you want an example using .NET 2.0.
 
Now we are ready to start.
 

1. Create new Class Library project and name it MockTutorial.

MockTutorial project

2. Rename Class1 to DirectoryInfoSample so your code looks like this:

   1: namespace MockTutorial
   2: {
   3:     public class DirectoryInfoSample
   4:     {
   5:     }
   6: }
 
3. Add a test class.  For simplicity we add our test class in the same file.  The name of the test class will be DirectoryInfoSampleTests.
   1: public class DirectoryInfoSampleTests
   2: {
   3: }
 

4. We need to add references to our unit test framework, Rhino Mocks, and SystemWrapper libraries.

MockTutorial ref 

5. Create our first test.  Remember that our method should try to create directory and there two possible cases (directory doesn’t exist and directory exists). It means that we’ll need two separate tests.  Let’s create the first test when directory already exists.The signature for our method under test will be  public bool TryToCreateDirectory(IDirectoryInfoWrap directory)You also will need to add using statements for your unit testing framework, Rhino Mocks, and SystemWrapper:

   1: using SystemWrapper.IO;
   2: using MbUnit.Framework;
   3: using Rhino.Mocks;
 

 Here comes the test.

   1: [Test]
   2: public void When_try_to_create_directory_that_already_exists_return_false()
   3: {
   4:     var directoryInfoStub = MockRepository.GenerateStub<IDirectoryInfoWrap>();
   5:     directoryInfoStub.Stub(x => x.Exists).Return(true);
   6:     Assert.AreEqual(false, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));
   7: }
Line 4 creates the stub object for DirectoryInfo.
Line 5 stubs Exists property and return true that means that the directory exists.
Line 6 verifies that TryToCreateDirectory method returns false that means that directory wasn’t created because it already exists.
 

6. If you try to compile, it’s going to fail because we didn’t create TryToCreateDirectory method.

Let’s create the method that is going to satisfy our test.

   1: public bool TryToCreateDirectory(IDirectoryInfoWrap directory)
   2: {
   3:     return false;
   4: }
You just can see that we wrote minimum code to make our test pass successfully.
 

7. Next we want to create our second test that expects that directory doesn’t exists and creates it.

   1: [Test]
   2: public void When_try_to_create_directory_that_does_not_exist_return_true()
   3: {
   4:     var directoryInfoStub = MockRepository.GenerateStub<IDirectoryInfoWrap>();
   5:     directoryInfoStub.Stub(x => x.Exists).Return(false);
   6:     Assert.AreEqual(true, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));
   7: }
 
You can see our second test looks very similar to the first one.  The only difference, beside the test name, is that when we stub Exists property we return false instead of true.

If you try to run the test, it will fail because in our test we expect TryToCreateDirectory method to return true.

8. It’s time again to work on our method under test.

   1: public bool TryToCreateDirectory(IDirectoryInfoWrap directory)
   2: {
   3:     if (directory.Exists)
   4:         return false;
   5:  
   6:     return true;
   7: }

Now our tests should pass.  Wait, but how do we know if the directory was created?

 
9. Modify our test to check that Create() method was called.
 
We can change our stub to mock and create an expectation for Create. If you’re confused about Mocks and Stubs, you can read Mocks aren’t Stubs by Martin Fowler.  The last we verify that Create was executed:
   1: [Test]
   2: public void When_try_to_create_directory_that_does_not_exist_return_true()
   3: {
   4:     var directoryInfoMock = MockRepository.GenerateMock<IDirectoryInfoWrap>();
   5:     directoryInfoMock.Stub(x => x.Exists).Return(false);
   6:     directoryInfoMock.Expect(x => x.Create());
   7:     Assert.AreEqual(true, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoMock));
   8:  
   9:     directoryInfoMock.VerifyAllExpectations();
  10: }
 

It will work but I prefer to use stubs and call new method in Rhino Mocks AssertWasCalled.  Isn’t it looks cleaner?

   1: [Test]
   2: public void When_try_to_create_directory_that_does_not_exist_return_true()
   3: {
   4:     var directoryInfoStub = MockRepository.GenerateStub<IDirectoryInfoWrap>();
   5:     directoryInfoStub.Stub(x => x.Exists).Return(false);
   6:     Assert.AreEqual(true, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));
   7:  
   8:     directoryInfoStub.AssertWasCalled(x => x.Create());
   9: }
 
If you run our second test that we just modified, it will fail.  Of course, we never called Create method.

 

10. Call Create() in our TryToCreateDirectory method.

   1: public bool TryToCreateDirectory(IDirectoryInfoWrap directory)
   2: {
   3:     if (directory.Exists)
   4:         return false;
   5:  
   6:     directory.Create();
   7:     return true;
   8: }
 
11. We also can modify our first test to make sure Create() wasn’t call in case when directory already exists.

In this case we call Rhino Mocks method AssertWasNotCalled.

   1: [Test]
   2: public void When_try_to_create_directory_that_already_exists_return_false()
   3: {
   4:     var directoryInfoStub = MockRepository.GenerateStub<IDirectoryInfoWrap>();
   5:     directoryInfoStub.Stub(x => x.Exists).Return(true);
   6:     Assert.AreEqual(false, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));
   7:  
   8:     directoryInfoStub.AssertWasNotCalled(x => x.Create());
   9: }
 
To see all the classes that wrapped by SystemWrapper follow this link.
 
More to come.  I’d like to hear from you what classes would you like to add to SystemWrapper first.
 

kick it on DotNetKicks.com

About these ads

7 Responses to “Tutorial to TDD using Rhino Mocks and SystemWrapper.”

  1. Damian said

    Great tutorial.. Well structured and easy to understand, while still giving a solid coverage of the fundamentals..

  2. Vadim said

    Damian, thanks

  3. Iain said

    Great tutorial, I have come across this issue many times and SystemWrapper nicely solves it.

    I have added a few more classes for System.IO – see the patch on codeplex.

    Using the Funq DI container, it is also possible to wrap classes which require parameters to the constructor (MemoryStream etc.).

  4. Vadim said

    Iain,
    Thanks a lot for submitting a patch. I added you as a developer on the project so feel free to commit any changes.

  5. Sunit Joshi said

    Very informational and clear. Hope to see more.

    rgds
    Sunit

  6. Adrian Zhao said

    Vadim:

    Great tutorial. Could you send me the .Net 2.0 example code?

    Thanks,
    Adrian

    • Vadim said

      Andrian,

      You can get sample code from http://systemwrapper.codeplex.com/SourceControl/ListDownloadableCommits.aspx. All samples in .Net 3.5. In .Net 2.0 on of the example is going to look something like this:

      [Test]
      public void When_try_to_create_directory_that_does_not_exist_return_true_dot_NET_2()
      {
      IDirectoryInfoWrap directoryInfoStub =
      MockRepository.GenerateStub();
      RhinoMocksExtensions.Stub(directoryInfoStub,
      delegate(IDirectoryInfoWrap dirInfo)
      {
      bool b = dirInfo.Exists;
      }).Return(false);
      Assert.AreEqual(true, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));
      RhinoMocksExtensions.AssertWasCalled(directoryInfoStub,
      delegate(IDirectoryInfoWrap dirInfo)
      {
      dirInfo.Create();
      });
      }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: