TDD : Introduction to Rhino Mocks

Rhino Mocks is the most popular Mock Object Framework for .NET. The purpose of this blog entry is to provide a brief introduction to Rhino Mocks. In particular, I want to describe how you can use Rhino Mocks when building ASP.NET MVC web applications.

In the first part of this entry, I explain why Mock Object Frameworks are critical tools when performing Test-Driven Development. Next, I discuss how you can use Rhino Mocks to create both state verification unit tests and behavior verification unit tests. Finally, I discuss how Rhino Mocks forces you to design your ASP.NET MVC web applications in a particular way.

Why Mock?

Why should you care about Mock Object Frameworks such as Rhino Mocks? If you want to practice Test-Driven Development, then there is no way to avoid using a Mock Object Framework. You need to use a Mock Object Framework to create effective unit tests.

A unit test enables you to test a single unit of code in isolation. Typically, a unit of code corresponds to a single method in your application. Therefore, a unit test should enable you to test just the code inside a particular method and nothing else.

A unit test created for the purposes of Test-Driven Development — a TDD unit test — has additional requirements. A unit test appropriate for TDD unit test should execute very quickly and should not require any application configuration.

When practicing Test-Driven Development, you execute all of your tests whenever you make a code change. Most likely, you’ll execute your unit tests hundreds of times while building an application. If your unit tests are too slow or they take work to setup, then Test-Driven Development will no longer be practical.

Let’s look at a particular code sample. The method in Listing 1 adds two numbers together.

Listing 1 – Calculate.cs

   1:  using System;
   2:   
   3:  public class Calculate
   4:  {
   5:   
   6:      public int AddNumbers(int num1, int num2)
   7:      {
   8:          return num1 + num2;
   9:      }
  10:  }

Listing 2 contains a unit test for the method in Listing 1. The unit test in Listing 2 tests whether the method in Listing 1 returns the correct value for 2 + 2.

Listing 2 – AddNumbersTest Method

   1:  [TestMethod]
   2:  public void AddNumbersTest()
   3:  {
   4:      Calculate calculate = new Calculate();
   5:      int result = calculate.AddNumbers(2, 2);
   6:      Assert.AreEqual(2 + 2, result);
   7:  }

There is nothing wrong with the unit test in Listing 2. This unit test enables you to test the AddNumbers() method in isolation. The unit test executes quickly without requiring you to perform any configuration. You could run hundreds of unit tests that look just like this one each time you make a code change without significantly slowing down the process of developing an application.

Unfortunately, most real-world code looks nothing like the code in Listing 1. Most real-world code has dependencies on external objects. In many cases, these external objects have dependencies on resources like databases, configuration files, web services, or the file system.

For example, consider the code in Listing 3. The GetProducts() method in Listing 3 looks more like it was ripped from an actual application.

Listing 3 – GetProducts Method

   1:  public static List<Product> GetProducts()
   2:  {
   3:      // Get database connection string
   4:      string conString = ConfigHelper.GetDBConnectionString();
   5:      
   6:      // Get data provider
   7:      DataProvider dp = new DataProvider(conString);
   8:      
   9:      // Return list of products
  10:      return dp.GetProducts();
  11:  }

The GetProducts() method references two external classes named ConfigHelper and DataProvider. The ConfigHelper class is used to retrieve a database connection string. The DataProvider class is used to access the database.

The unit test in Listing 4 tests the GetProducts() method.

Listing 4 – GetProductsTest Method

   1:  [TestMethod]
   2:  public void GetProductsTest()
   3:  {
   4:      List<Product> results = Product.GetProducts();
   5:      Assert.AreEqual(3, results.Count);
   6:  }

The unit test in Listing 4 checks whether a particular number of products is returned by the GetProducts() method.

Here’s the problem: the test in Listing 4 depends on external resources. These external resources violate the requirements for a good TDD test.

Each time you execute the test in Listing 4, a connection string must be retrieved from the ConfigHelper class. The ConfigHelper class, in turn, retrieves the connection string from a configuration file. The test has a dependency on an external resource. In this case, the external resource is a configuration file. In order to run the unit test, you must have the right configuration file setup in your Test Project.

Furthermore, the unit test in Listing 5 has a dependency on the DataProvider class. The DataProvider class relies on an external resource: a database. In order for the test to run, the product records must be retrieved from a database table. Retrieving data from a database is slow. Imagine running hundreds of tests that must access a database whenever you make a code change. You would never get any work done on your application. You would spend all day waiting for your unit tests to finish executing.

If you want to be able to write an effective test for the GetProducts() method, then you need to take advantage of a Mock Object Framework. A Mock Object Framework enables you to mock external resources such as configuration files and databases. The remainder of this blog entry focuses on a particular Mock Object Framework: Rhino Mocks.

State versus Behavior Verification

A Mock Object Framework such as Rhino Mocks can be used to perform two very different types of unit tests. You can use Rhino Mocks to perform either state or behavior verification (This distinction used to be called state versus interaction-based testing and many people continue to use these terms).

On the one hand, you can use a Mock Object Framework to create stubs. A stub acts as a stand-in for a normal object. There are multiple reasons that you might create a stub. For example, as discussed above, the actual object might access an external resource such as a database or the file system causing the actual object to be too slow to use in a unit test. The stub enables you to perform a test in a reasonable amount of time without requiring any configuration.

Another and equally valid reason for using a stub is that you haven’t actually implemented a particular object required for a test. For example, you might want to unit test a method that relies on a DataProvider object, but you have not had a chance to implement the data provider object. In this case, the mock object is acting as a stand-in for the real object so that you can build other objects that depend on the stub.

When performing state-based verification, the final statement in your unit test is typically an assert statement that asserts that some condition is true.

When performing behavior verification (an interaction test), on the other hand, you are interested in verifying that a set of objects behave and interact in a particular way. For example, you might want to verify that that when the DataProvider.GetProducts() method is called, a second method named the SqlDataProvider.GetProducts() method is called exactly once with a particular set of parameters or that another method named the SqlDataProvider.ExecuteCommand() method is called exactly three times with another particular set of parameters .

When performing behavior verification, your test typically does not end with an assert statement. Instead, the interaction of the objects being tested is verified. Rhino Mocks throws an exception automatically when mock expectations do not meet reality.

To learn more about state versus behavior verification, and the distinction between mocks and stubs, see Martin Fowler’s article at:

http://martinfowler.com/articles/mocksArentStubs.html

Using Rhino Mocks

Rhino Mocks was created and it is maintained by Ayende Rahien (AKA Oren Eini). You can download Rhino Mocks from the following URL:

http://www.ayende.com/projects/rhino-mocks.aspx

There is a Google group devoted to discussing Rhino Mocks (Ayende Rahien is an active participant) at:

http://groups.google.com/group/RhinoMocks

Rhino Mocks does not include an installer. After you download and unzip Rhino Mocks, you can use Rhino Mocks in a project by adding a reference to the Rhino.Mocks.dll assembly. There is also an XML file included with the download that provides Intellisense for Rhino Mocks within Visual Studio.

One warning about using Rhino Mocks on Windows Vista. Vista will prevent you from using assemblies that you download from the Internet. Before you reference the Rhino.Mocks.dll assembly in Visual Studio, you need to Unblock the assembly: right-click the assembly file and click the Unblock button under the General tab (see Figure 1).

image

State Verification with Rhino Mocks

You can use Rhino Mocks to create stubs for interfaces, abstract classes, and concrete classes. When creating a stub for class methods, the method must be marked as virtual. This last requirement places some significant limitations on what you can stub. You cannot use Rhino Mocks with static or sealed methods (we’ll return to this issue in the last section of this blog entry).

Let’s start with a simple sample of a stub. Imagine that you have created the abstract base class in Listing 5.

Listing 5 – ProductBase.cs

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public abstract class ProductBase
   6:      {
   7:          public abstract string Name { get; set; }
   8:   
   9:          public abstract decimal Price { get; set; }
  10:   
  11:          public abstract void Save();
  12:      }
  13:  }

You intend, at some point in the future, to create particular types of products that derive from this base class – for example, ElectronicProduct, FoodProduct, SportsProduct — but you haven’t gotten around to creating these concrete classes yet. No worries. By taking advantage of Rhino Mocks, you can pretend that you have already done the work. The test in Listing 6 uses Rhino Mocks to create a concrete instance of the class, set a property, and test the property.

Listing 6 – RhinoMocksTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class RhinoMocksTest
  14:      {
  15:   
  16:          [TestMethod]
  17:          public void TestStubAbstract()
  18:          {
  19:              // Setup product stub
  20:              ProductBase product = MockRepository.GenerateStub<ProductBase>();
  21:              product.Name = "Laptop Computer";
  22:              product.Price = 3200.00m;
  23:   
  24:              // Test
  25:              Assert.AreEqual(3200.00m, product.Price);
  26:          }
  27:   
  28:      }
  29:  }

In Listing 6, the static method MockRepository.GenerateStub<T>() is called to generate a stub for the abstract ProductBase class. After you generate the stub, you can treat the stub as a normal class and set and read its properties. The last assert statement returns the value True since the stub product’s Price property was, in fact, set to the value $3,200.00.

You also can create stubs for interfaces in the exact same way. For example, Listing 7 contains an IProduct interface.

Listing 7 – IProduct.cs

   1:  using System;
   2:   
   3:  public interface IProduct
   4:  {
   5:      string Name { get; set; }
   6:   
   7:      decimal Price { get; set; }
   8:  }

Imagine that you are adding a new feature to your store. You are creating a method that doubles the price of any product. The method is contained in Listing 8.

Listing 8 – ProductManager.cs

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public class ProductManager
   6:      {
   7:   
   8:          public static void DoublePrice(IProduct product)
   9:          {
  10:              product.Price *= 2;
  11:          }
  12:   
  13:      }
  14:  }

Before you can test the method in Listing 8, you need a class that implements the IProduct interface. If you don’t want to do the work to implement the interface at the moment, then you can use Rhino Mocks to create a stub from the interface automatically. The test in Listing 9, once again, takes advantage of the MockRepository.GenerateStub<T>() method to generate a concrete stub from an interface.

Listing 9 – RhinoMocksTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class RhinoMocksTest
  14:      {
  15:   
  16:          [TestMethod]
  17:          public void TestStubInterface()
  18:          {
  19:              decimal price = 3200.00m;
  20:   
  21:              // Setup product stub
  22:              IProduct product = MockRepository.GenerateStub<IProduct>();
  23:              product.Name = "Laptop Computer";
  24:              product.Price = price;
  25:   
  26:              // Call method being tested
  27:              ProductManager.DoublePrice(product);
  28:   
  29:              // Test
  30:              Assert.AreEqual(price * 2, product.Price); 
  31:          }
  32:      }
  33:  }

The test in Listing 9 creates a concrete instance of a class that implements the IProduct interface and passes the instance to the DoublePrice() method. The test demonstrates that the DoublePrice() method does, in fact, double the price of the product correctly.

Setting Up Return Values from Stub Methods

You also can use Rhino Mocks to generate fake return values from classes and interfaces that you have stubbed. Here’s a common scenario. Imagine that you need to test a method that relies on database data. However, you don’t want to access the database when you execute the unit test because accessing the database would be too slow. In this case, you can create a stub method that always returns a hard-coded set of values.

The interface in Listing 10 could be used to represent your data access layer.

Listing 10 – IProductRepository.cs

   1:  using System;
   2:  using System.Collections.Generic;
   3:   
   4:  public interface IProductRepository
   5:  {
   6:      IProduct Get(int ProductId); 
   7:      
   8:      IEnumerable<IProduct> Select();
   9:   
  10:      bool Save(IProduct product);
  11:  }

The interface in Listing 10 includes a method for retrieving a set of product records, a method for retrieving a particular product record, and a method for saving a product record.

The unit test in Listing 11 illustrates how you can create a stub for the IProductRepository interface and setup the stub’s Select() method so that it always returns a fake set of products.

Listing 11 – RhinoMocksTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class RhinoMocksTest
  14:      {
  15:          private IEnumerable<IProduct> _fakeProducts = new List<IProduct>
  16:              {
  17:                  new Product {Name = "Steak", Price = 9.85m},
  18:                  new Product {Name = "Milk", Price = 2.02m},
  19:                  new Product {Name = "Diapers", Price = 33.07m}
  20:              };
  21:   
  22:   
  23:          [TestMethod]
  24:          public void TestStubInterfaceMethod()
  25:          {
  26:              MockRepository mocks = new MockRepository();
  27:              IProductRepository products = mocks.Stub<IProductRepository>();
  28:   
  29:              using (mocks.Record())
  30:              {
  31:                  SetupResult.For(products.Select()).Return(_fakeProducts);
  32:              }
  33:   
  34:              var results = products.Select();
  35:              
  36:              Assert.AreEqual(3, results.Count());
  37:          }
  38:   
  39:      }
  40:  }

There are three important differences that you should notice between the code in Listing 11 and the code in the previous samples. First, notice that the sub for the IProductRepository interface is not created by using the GenerateStub<T>() method like in previous code samples. When setting up method return values, you must create an instance of the Rhino Mocks MockRepository class and call the MockRepository instance’s Stub<T>() method.

Second, notice that the SetupResult class is used to setup the return value for the IProductRepository.Select() method. When the Select() method is called, the contents of the _fakeProducts field is returned.

Finally, notice that the call to SetupResult is wrapped in a using statement that references the MockRespository.Record() method. The using statement in conjunction with the Record() method are used to record how the stub should behave when a particular stub method is called. You can setup multiple stub methods within the single using statement.

You can even return different values from a stub method when different parameters are passed to the stub method. For example, the test in Listing 12 returns different products depending on the ProductId passed to the ProductRepository.Get() method.

Listing 12 – RhinoMocksTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class RhinoMocksTest
  14:      {
  15:   
  16:          [TestMethod]
  17:          public void TestStubMultipleReturn()
  18:          {
  19:              MockRepository mocks = new MockRepository();
  20:              IProductRepository products = mocks.Stub<IProductRepository>();
  21:   
  22:              using (mocks.Record())
  23:              {
  24:                  SetupResult
  25:                      .For(products.Get(2))
  26:                      .Return(new Product {Name="Beer", Price=12.99m });
  27:   
  28:                  SetupResult
  29:                      .For(products.Get(12))
  30:                      .Return(new Product { Name = "Steak", Price = 8.02m });
  31:              }
  32:   
  33:              // Test
  34:              IProduct product1 = products.Get(2);
  35:              Assert.AreEqual("Beer", product1.Name);
  36:   
  37:              IProduct product2 = products.Get(12);
  38:              Assert.AreEqual("Steak", product2.Name);
  39:   
  40:              IProduct product3 = products.Get(13);
  41:              Assert.IsNull(product3);
  42:          }
  43:   
  44:      }
  45:  }

In Listing 12, two different products are returned when calling the Get() method depending on the value of the ProductId. In the Record() section of the test, the two different return values for the Get() method are setup.

Notice the very last assert statement. If you call the Get() method with a ProductId that has not been setup, then the value Null is returned.

If you want any call to the Get() method to always return a particular fake product, then you can call IgnoreArguments() when setting up the return value. This approach is illustrated by the test in Listing 13. As the assert statements at the end of the test method demonstrate, regardless of the ProductId passed to the Get() method, the very same product is returned.

Listing 13 – RhinoMocksTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      /// <summary>
  13:      /// Summary description for TestRhino
  14:      /// </summary>
  15:      [TestClass]
  16:      public class RhinoMocksTest
  17:      {
  18:   
  19:          [TestMethod]
  20:          public void TestStubIgnoreArguments()
  21:          {
  22:              MockRepository mocks = new MockRepository();
  23:              IProductRepository products = mocks.Stub<IProductRepository>();
  24:   
  25:              using (mocks.Record())
  26:              {
  27:                  SetupResult
  28:                      .For(products.Get(1))
  29:                      .IgnoreArguments()
  30:                      .Return(new Product { Name = "Beer", Price = 12.99m });
  31:              }
  32:   
  33:              // Test
  34:              IProduct product1 = products.Get(2);
  35:              Assert.AreEqual("Beer", product1.Name);
  36:   
  37:              IProduct product2 = products.Get(12);
  38:              Assert.AreEqual("Beer", product2.Name);
  39:          }
  40:   
  41:      }
  42:  }

Behavior Verification with Rhino Mocks

You can use Rhino Mocks to verify that a particular set of objects interact in an expected way. For example, you can verify that a particular object method was called the expected number of times with the expected set of parameters. This type of testing is also called interaction-based testing.

This type of test is useful when you cannot verify the state of an object after you interact with the object. For example, an object might not have a public property that you can perform an assert against. Therefore, there is no direct way to validate the state of the object after executing the unit test.

For example, imagine that you need to create a logging component. Every time you perform a significant action in your application, you want to log the action to a log file on disk. (This example of behavior verification is taken from Gerard Meszaros’s xUnit Test Patterns book, see http://xunitpatterns.com/Behavior%20Verification.html). If the logger component does not have a property that exposes all of its log entries then there will be no easy way to verify whether the logger is behaving as expected.

However, if you can intercept requests to the logger component, then you can verify that other components are interacting with the logger component when you expect. The point of behavior verification is to perform this type of test of the interaction between different components.

Expectations versus Reality

When performing behavior verification tests with Rhino Mocks, your test code is divided into two sections. First, you have a section of code where you record your expectations. Second, you have a section of code where your expectations are tested against reality.

For example, Listing 14 contains a unit test for a logger component. In the first section of the test, a particular set of expectations is recorded. When the Customer.Save() method is called, the Logger.Log() method should be called with the ProductId of the product being saved.

Listing 14 – LoggerTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using Rhino.Mocks;
   8:  using RhinoMockProject;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class LoggerTest
  14:      {
  15:   
  16:          [TestMethod]
  17:          public void LogTest()
  18:          {
  19:              MockRepository mocks = new MockRepository();
  20:              Logger logger = mocks.CreateMock<Logger>();
  21:              using (mocks.Record())
  22:              {
  23:                  logger.Log(27);
  24:              }
  25:              using (mocks.Playback())
  26:              {
  27:                  Customer newCustomer = new Customer(27, logger);
  28:                  newCustomer.Name = "Stephen Walther";
  29:                  newCustomer.Save();
  30:              }
  31:          }
  32:      }
  33:  }

If you run the test in Listing 14, and the Logger.Log() method is not called with the expected value for CustomerId, then the unit test fails. Notice that the unit test does not contain an assert statement. If expectations do not match reality, Rhino Mocks causes the unit test to fail by raising an ExpectationViolationException exception.

The Customer class is contained in Listing 15. Notice that the Logger component is passed to the Customer class in the Customer class constructor. Passing a class in this manner is a type of dependency injection called constructor injection (see Martin Fowler, http://martinfowler.com/articles/injection.html).

Listing 15 – Customer.cs

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public class Customer
   6:      {
   7:          public int Id { get; private set; }
   8:          public string Name { get; set; }
   9:          private Logger _logger;
  10:   
  11:          public Customer(int Id, Logger logger)
  12:          {
  13:              this.Id = Id;
  14:              _logger = logger;
  15:          }
  16:   
  17:          public void Save()
  18:          {
  19:              _logger.Log(this.Id);
  20:          }
  21:   
  22:      }
  23:  }

The Logger class is contained in Listing 16. This class isn’t really implemented since the Log() method is never really called. The Log() method raises an exception. Since we are mocking the Log() method, this exception is never raised.

Listing 16 – Logger.cs

   1:  using System;
   2:   
   3:  public class Logger
   4:  {
   5:      public virtual void Log(int ProductId)
   6:      {
   7:          throw new Exception("eeeks!");
   8:      }
   9:   
  10:  }

Strict, Non-Strict, and Partial Mocking

Rhino Mocks supports three different ways to create mock objects. You can mock an object by calling any of the following three methods:

1. CreateMock<T>() – This method of creating a mock object enforces a strict replay of expectations. If a method is called unexpectedly, then the mock object will fail verification and throw an exception.

2. DynamicMock<T>() – This method of creating a mock object permits a looser replay of expectations. If a method is called unexpectedly, then the mock object will not fail verification and no exception is thrown.

3. PartialMock<T>() – This method of creating a mock object can only be performed on classes. Only certain methods are mocked. Other methods of the class can be called normally.

Listing 17 contains a class named Rover. Rover has two methods named Bark() and Fetch(). The unit tests in Listings 18 contrast the three methods of mocking Rover.

Listing 17 – Rover.cs

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public class Rover
   6:      {
   7:   
   8:          public virtual void Bark(int loudness)
   9:          {
  10:              // Make loud noise
  11:          }
  12:   
  13:          public virtual void Fetch(int speed)
  14:          {
  15:              // Fetch something
  16:              throw new Exception("Yikes!");
  17:          }
  18:      
  19:      }
  20:  }

Notice that both of Rover’s methods are marked as virtual methods. This is a requirement when using Rhino Mocks. When mocking a class, only virtual (and not sealed or static) methods can be mocked.

Notice, furthermore, that the Fetch() method throws an exception. When this method is mocked, this exception won’t be thrown because the actual method won’t ever be called.

Listing 18 – RoverTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using RhinoMockProject;
   8:  using Rhino.Mocks;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class RoverTest
  14:      {
  15:          [TestMethod]
  16:          public void BarkTestStrictReplay()
  17:          {
  18:              MockRepository mocks = new MockRepository();
  19:              Rover rover = mocks.CreateMock<Rover>();
  20:              using (mocks.Record())
  21:              {
  22:                  rover.Bark(17);
  23:                  LastCall
  24:                      .IgnoreArguments()
  25:                      .Repeat.Times(2);
  26:              }
  27:              using (mocks.Playback())
  28:              {
  29:                  rover.Bark(17);
  30:                  rover.Bark(23);
  31:                  // rover.Bark(2); // fail
  32:                  // rover.Fetch(2); // fail
  33:              }
  34:          }
  35:   
  36:          [TestMethod]
  37:          public void BarkTestNonStrictReplay()
  38:          {
  39:              MockRepository mocks = new MockRepository();
  40:              Rover rover = mocks.DynamicMock<Rover>();
  41:              using (mocks.Record())
  42:              {
  43:                  rover.Bark(17);
  44:                  LastCall
  45:                      .IgnoreArguments()
  46:                      .Repeat.Times(2);
  47:              }
  48:              using (mocks.Playback())
  49:              {
  50:                  rover.Bark(17);
  51:                  rover.Bark(23);
  52:                  rover.Bark(2); // pass
  53:                  rover.Fetch(2); // pass
  54:              }
  55:          }
  56:   
  57:          [TestMethod]
  58:          public void BarkTestPartialReplay()
  59:          {
  60:              MockRepository mocks = new MockRepository();
  61:              Rover rover = mocks.PartialMock<Rover>();
  62:              using (mocks.Record())
  63:              {
  64:                  rover.Bark(17);
  65:                  LastCall
  66:                      .IgnoreArguments()
  67:                      .Repeat.Times(2);
  68:              }
  69:              using (mocks.Playback())
  70:              {
  71:                  rover.Bark(17);
  72:                  rover.Bark(23);
  73:                  rover.Bark(2); // pass
  74:                  // rover.Fetch(2); // throws exception
  75:              }
  76:          }
  77:   
  78:      }
  79:  }

Listing 18 contains three tests that test the same Rover class. The tests differ in how Rover is mocked.

The first test — named BarkTestStrictReplay() — uses CreateMock<T>() to create an instance of Rover. The CreateMock<T>() method enforces strict expectations. If you don’t make the exact method calls setup in the expectations section, then the test fails when the expectations are played back against reality.

For example, in this test, you can’t cause Rover to bark a third time since the expectation was setup that Rover would only bark twice. Also, you can’t call the Fetch() method since no expectations were setup concerning this method.

The next test is named BarkTestNonStrictReplay(). In this test, Rover is created with the DynamicMock<T>() method. This method of creating a mock object allows for looser expectations. Calling the Bark() method a third time, or calling an unexpected method like Fetch(), does not cause the test to fail.

Finally, the third test illustrates how you can mock Rover using the PartialMock<T>() method. The PartialMock<T>() method does not mock all of Rover’s methods and properties. In the test in Listing 18, Rover’s Bark() method is mocked but not his Fetch() method. When Fetch() is called, an exception is thrown since the actual Fetch() method throws an exception (see Listing 17).

Creating Testable Web Applications

In this last section, I want to draw your attention to a controversial topic. If you want to use Rhino Mocks to test an application, then you are forced to write your application in a particular way. Some people think this requirement is a virtue since it forces your application to have a testable design. Other people believe that the design of your application should not be dictated by the limitations of a particular tool.

Rhino Mocks places two important constraints on the design of your application. First, since Rhino Mocks cannot be used to mock static or sealed methods, you are encouraged to avoid both static and sealed methods.

Second, because you cannot mock what you cannot see, you are encouraged to follow a particular pattern called Dependency Injection when building an application with Rhino Mocks (see Martin Fowler, http://martinfowler.com/articles/injection.html). There are several variations of the Dependency Injection pattern, but the basic idea is that you should avoid instantiating classes within other classes. Instead, if one class is dependent on other classes, then you should pass these dependencies to the class when the class is initialized. Following this pattern makes it easier to mock the dependencies of a class.

Let’s consider a particular code sample in which both of these limitations of Rhino Mocks is important. Imagine that you decide to create a Logger component for your application. When any method of your application is called, you want to log the action to a file on disk. If I didn’t care about Rhino Mocks, I would use the code in Listing 19 to create the Logger component.

Listing 19 – Logger.cs (First iteration)

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public class Logger
   6:      {
   7:          public static void Write(string message)
   8:          {
   9:              // Log message to file system
  10:          }
  11:      }
  12:  }

Notice that the Logger in Listing 19 uses a static method to write to the log file. The advantage of using a static method is that it saves a line of code when calling the method since you don’t need to instantiate the class before using it. For example, the DataProvider class in Listing 20 calls Logger.Write() in both of its methods.

Listing 20 – DataProvider.cs (First Iteration)

   1:  using System;
   2:  using System.Collections.Generic;
   3:   
   4:  namespace RhinoMockProject
   5:  {
   6:   
   7:      public class DataProvider
   8:      {
   9:          public static IEnumerable<Product> GetProducts()
  10:          {
  11:              Logger.Write("Getting products");
  12:   
  13:              // Get products from database
  14:              return null;
  15:          }
  16:   
  17:   
  18:          public static bool SaveProduct(Product product)
  19:          {
  20:              Logger.Write("Saving new product");
  21:   
  22:              // Save product to database
  23:              return true;
  24:          }
  25:   
  26:   
  27:      }
  28:  }

The problem with this approach to building a Logger component is that it is not compatible with Rhino Mocks. The Logger class is not Rhino Mocks mockable for two reasons. First, you cannot mock the Logger.Write() method since it is a static method. Second, you cannot mock the Logger class when it is used within the DataProvider class since the Logger class is not exposed outside of the DataProvider class (you cannot mock what you cannot see).

Listing 21 contains a mockable version of the Logger class. In this revised version, the Write() method is a virtual instance method rather than a static method.

Listing 21 – Logger.cs (Second Iteration)

   1:  using System;
   2:   
   3:  namespace RhinoMockProject
   4:  {
   5:      public class Logger
   6:      {
   7:          public virtual void Write(string message)
   8:          {
   9:              // Log message to file system
  10:          }
  11:      }
  12:  }

The DataProvider class in Listing 22 has been revised to support Dependency Injection. The new DataProvider class accepts an instance of the Logger class in its constructor.

Listing 22 – DataProvider.cs (Second Iteration)

   1:  using System;
   2:  using System.Collections.Generic;
   3:   
   4:  namespace RhinoMockProject
   5:  {
   6:      public class DataProvider
   7:      {
   8:          private Logger _logger;
   9:   
  10:          public DataProvider(Logger logger)
  11:          {
  12:              _logger = logger;
  13:          }
  14:   
  15:          public virtual IEnumerable<Product> GetProducts()
  16:          {
  17:              _logger.Write("Getting products");
  18:   
  19:              // Get products from database
  20:              return null;
  21:          }
  22:   
  23:          public virtual bool SaveProduct(Product product)
  24:          {
  25:              _logger.Write("Saving new product");
  26:   
  27:              // Save product to database
  28:              return true;
  29:          }
  30:      }
  31:  }

Finally, the test in Listing 23 illustrates how you can use Rhino Mocks to perform a behavior verification of the Logger and DataProvider class. Notice that a mock version of the Logger class is created and passed to an actual instance of the DataProvider class.

Listing 23 – LoggerTest.cs

   1:  using System;
   2:  using System.Text;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:   
   7:  using Rhino.Mocks;
   8:  using RhinoMockProject;
   9:   
  10:  namespace RhinoMockProjectTests
  11:  {
  12:      [TestClass]
  13:      public class LoggerTest
  14:      {
  15:          [TestMethod]
  16:          public void WriteTest()
  17:          {
  18:              MockRepository mocks = new MockRepository();
  19:              Logger logger = mocks.CreateMock<Logger>();
  20:              DataProvider dp = new DataProvider(logger);
  21:              using (mocks.Record())
  22:              {
  23:                  logger.Write("Saving new product");
  24:                  logger.Write("Getting products");
  25:              }
  26:              using (mocks.Playback())
  27:              {
  28:                  dp.SaveProduct(null);
  29:                  dp.GetProducts();
  30:              }
  31:          }
  32:   
  33:      }
  34:  }

The test in Listing 23 mocks the Logger class and injects the mock into the DataProvider’s constructor. The test sets up the expectations that the Logger.Write() method will be called twice with particular messages. In the Playback section, the DataProvider.SaveProduct() and DataProvider.GetProducts() methods are called, the expectations are matched, and the test passes.

If you are really interested in testable design, then you would most likely not stop here. The next step is to create an interface for the Logger class and pass the interface to the DataProvider constructor instead of the Logger class itself. You should be injecting ILogger instead of a particular logger. Out of laziness, I’ll stop here.

Before ending this section, it is worth mentioning that Typemock Isolator, another Mock Object Framework for .NET, does not have the limitations discussed in this section. You can use Typemock Isolator to mock static methods. Furthermore, you can mock objects without following the Dependency Injection pattern. Some people think this is a virtue of Typemock Isolator and some people think that this is a vice.

Summary

The purpose of this blog entry was to provide you with an introduction to Rhino Mocks. This entry was certainly not intended as a comprehensive discussion of all of the features of Rhino Mocks. The goal was to explain how you can use Rhino mocks to perform both state verification and behavioral verification unit tests. I also discussed some of the important limitations of Rhino Mocks and how these limitations affect how you build applications.

Discussion

  1. http:// says:

    thanks for this, I find it very useful

  2. http:// says:

    great primer. finally someone goes beyond testing a method that adds two numbers. thanks!

  3. http:// says:

    This is a great tutorial :) Thanks Stephen

  4. Lee says:

    Great tutorial. Clear and very thorough. Thanks for doing this.

  5. http:// says:

    Good explanations. Really enjoyed it.

  6. http:// says:

    Awesome, thanks.

  7. http:// says:

    Very good explained!

  8. http:// says:

    Best mock intro to date. Great job!

  9. http:// says:

    Great tutorial. I found it very useful.

  10. GEORGE says:

    Excellent Introduction to Mock Object Frameworks. Thank you!

  11. http:// says:

    Really nice tutorial. Needs to be one of the “Must read” for anyone looking at this.

    On the “Unblocking” isasue for the RhinoMocks dll and xml files, this is not Vista-only issue as I ran into it on a Windows XP system in a domain.

  12. http:// says:

    This is by far the best examples that I’ve seen using RhinoMocks! Thanks so much for doing this.

  13. http:// says:

    Congratullations!
    Very deep article to Mock! Thanks! Very useful!
    I add in my favorite links and send to tip to my friends!

  14. Russell Ball says:

    One of the best blog posts I’ve seen on the topic. Thanks!

  15. http:// says:

    Brief and to-the-point with lucid examples. Great introductory article on a subject that’s really hard to find good information on.

  16. http:// says:

    Great post. I had no clue what a mock was before this article. Now I see the benefits. I am confused as to what Mock Object Framework to use though. I like creating static facade classes that sit on top of my data access layer. These facades are always static, because there is no need to create an instance of these. Why create new instances when you don’t have to. Just takes up time and memory. Minimal but it adds up in large systems. These need to be tested and I like the idea of testing with DI. Does it just come down to choice? What are the pros and cons?

  17. Carel Lotz says:

    I just want to echo the sentiments of the other comments – this is a really great introduction to mocks and rhino mocks!

  18. http:// says:

    This is an awesome article!

  19. http:// says:

    Great article. It really helped clarify the practicality of implementing TDD principles in code with many external dependecies.

  20. http:// says:

    Great Tutorial

  21. Chuck Sphar says:

    Your post was a real help after trying to get Rhino from the wiki docs. Those were just too shorthanded for me. I learned a lot from you.

  22. http:// says:

    This article is a wonderful supplement to the documentation wiki on Ayende’s site! Excellent discussion on stubbing vs. mocking.

    On injection constructors: do you ever worry about your constructor signatures getting too big, or is it perhaps acceptable to have only dire essentials in the constructor with peripherals like loggers in public properties? Or maybe any given class shouldn’t have more internal objects than the axiomatic 5-7 that would come through the constructor in the first place?

    p.s. ASP Unleashed is pretty sweet so far!

  23. http:// says:

    @Alex – Glad you found the post useful.

    I share your concern that dependency injection might make your code more difficult to understand. I’m not sure whether a DI Framework (such as Unity) would improve matters.

    Thanks for buying my book!

  24. http:// says:

    Great job, dude. I tried learning from the wiki but I just couldn’t get it all. This should be in the wiki! Thank goodness I found this.

  25. Great intro to Rhino mocks!

  26. http:// says:

    When I tried to run listing 11 and 12 I kept getting:
    Error 103 The type or namespace name ‘Product’ could not be found (are you missing a using directive or an assembly reference?)
    I copied everything included in the post.
    The error went away when I created Product class that was implementing IProduct.
    Was there something I omitted, or we need that class?

  27. Yash says:

    Can you put the source code somewhere.

    Need to debug it to check the flow.

    Good Article.

    Thanks,
    Yash

  28. http:// says:

    Spent a couple of days trying to get my head around this area and this is simply THE best starter tutorial that exists!!

  29. Great summary – one of the best I have seen so far introducing Rhino mocking.

    Thx for writing.

  30. http:// says:

    TDD made simple. Good job..

  31. http:// says:

    Is there something I’m missing? On listing 11, I’m getting a compile error on line 36 on a Count property on the results which is declared as a var.

    Error 1 ‘System.Collections.Generic.IEnumerable‘ does not contain a definition for ‘Count’ and no extension method ‘Count’ accepting a first argument of type ‘System.Collections.Generic.IEnumerable‘ could be found (are you missing a using directive or an assembly reference?)

    I have the interfaces and the product in a model project while the test is in another project.

  32. http:// says:

    @Rene — Make sure that you import System.Linq or you won’t get the LINQ extension methods (such as Count()).

  33. http:// says:

    Stephen, that was it. I initially had the project as 2005 and when I converted it to 2008, I didn’t have the System.LINQ reference.

    Thanks again and let me say this is a great article/tutorial.

  34. http:// says:

    You always rocks!

  35. http:// says:

    A very nice Article…and a must for beginners who would like to learn about Rhino Mocks.

  36. http:// says:

    Thanks a lot. it was really useful to see missed pieces of Rhino Mocks

  37. Tim Barcz says:

    Stephen,

    This is very well written. Thank you for writing this. I’ve passed this article on the others who are starting with Rhino. I know how time consuming writing a blog post can be, so a post of this quality amazes me.

  38. http:// says:

    That is a good start for me to use Rhino Mocks.

  39. http:// says:

    Your post is really good! Exceptional *****

    The problem i see here is that using too much of mock seperates you from the real implementation.
    I am used to use Code Coverage to see if a fair amount of code is covered.
    From my understanding, mocks are use to remove the depencies.
    But Let’s say i want do not want to depend on a database and test if a Insert method of my service layer is working well buy returning the id of the inserted row.

    If I setup the expectations that it is return an Id of 1 and use mocks. None of the real method call would be executed and my test will pass. Well, what kind of value does this adds to my tests?

    There should be a guideline somewhere on when to mock and when not to mock! Otherwise my test will all pass but no real code will be executed!

    I would appreciate replies / comments on this!
    thanks

  40. http:// says:

    I was getting the same error as Peter Betlinski, for the Listing 11 and Listing 12:

    Error 103 The type or namespace name ‘Product’ could not be found (are you missing a using directive or an assembly reference?)

    Do we need to create the Product class that implements the IProduct interface ?

    Thanks,

    hadi teo.

  41. http:// says:

    Is there any possibility to use Rhino Mocks for mocking filesystem? Still don’t get how to use it in this way.

  42. http:// says:

    To get Listing 11 and Listing 12 working it appears we need to create a concrete class Product? I thought the idea behind Mocks was to be able to test using only Abstract classes or Interfaces?

  43. dotnetguts says:

    Thanks, it was good explanation.

    DotNetGuts
    http://dotnetguts.blogspot.com

  44. dotnetguts says:

    Good Information, Its really helped me, Thanks.

    I have few more Information on Rihno Mock, it might be of Interest dotnetguts.blogspot.com/…/…l-unit-testing.html

  45. Iain Holder says:

    Hi all,

    Too the chaps who are having trouble with listing 11 and listing 12, you will get a null reference if you mistakenly put the

    IProduct product1 = productRepository.Get(12);
    Assert.AreEqual(“Steak”, product1.Name);

    lines before the closing curly bracket of the using statement.

    Hope this helps

    Iain

  46. Terje says:

    Thx for this article.

    I did not understan behaviour testing before reading this and I have read quite a few articles on unit testing.

  47. Madhusudhana says:

    thanks,this is a good article and tutorial too..

  48. Hi..
    great and very useful posts..
    I see a lot of code here.. :)
    Thanks for sharing..

  49. hello…
    great topic…thanks for sharing…

  50. now….i can see more clearly on rhino…..thanks a lot.

  51. Melayu Boleh says:

    Hi..
    great introduction about Rhino..
    i learn it..
    Thanks admin..

  52. Melayu Boleh says:

    Hi all,

    Too the chaps who are having trouble with listing 11 and listing 12, you will get a null reference if you mistakenly put the

    IProduct product1 = productRepository.Get(12);
    Assert.AreEqual(“Steak”, product1.Name);

    lines before the closing curly bracket of the using statement.

    Hope this helps

    Iain

  53. stu says:

    Hello
    Great article…

    I am slightly confused about the use of static methods.
    You say that static methods cannot be mocked, and yet in Listing 8 there is this line:
    public static void DoublePrice(IProduct product)
    which listing 9 subsequently calls like this:
    ProductManager.DoublePrice(product);

    Is the static method in listing 8 allowed because it’s object is not actually being mocked, but rather just called by listing 9 please?

    thanks
    Stu

  54. Melayu Boleh says:

    Long and really great explaination.. thanks

  55. Thanks for giving the brief about Rhino Mocks.

  56. Thanks for sharing very significant blog.

  57. Very useful, Rhino Mocks this is the first I heard this.

  58. Awek Comel says:

    Thanks for the info

  59. CHARGE BACK RW W Great article, though – thanks!

  60. v2q4 I tried to mock a call to a Linq to SQL query, but I am struggling.

  61. v2q4 I tried to mock a call to a Linq to SQL query, but I am struggling. i like.

  62. I think that it is really great post, thanks.

  63. f422
    I believe it is a promising (currently version 4.0). So I would stick with it.. thanks

  64. I wish i can learn more. thanks br0

  65. very long and detailed article..
    love this..tqvm :)

  66. This is a great introduction to the subject of mocking using Moq framework. I believe it is a promising. I have checked the javascript which doesn’t seem to have any error in it.

  67. But, for some reason, i cannot hit the controller action while on onChange of the first dropdown list. I checked the javascript which doesnt seem to have any typos or errors in it.

  68. great primer. finally someone goes beyond testing a method that adds two numbers. thanks!

  69. Thank you for sharing this articles

  70. Long and really great explaination..

  71. Long and really great explaination..

  72. Really interesting articles.I enjoyed reading it. I need to read more on this topic..

  73. Easy option to get useful information as well as share good stuff with good ideas and concepts

  74. Really enjoyed reading this blog, please keep posting new info, have bookmarked your page.

  75. Depending on the type of application, it may require the development of an entirely different browser-based

  76. Wow you went a long way to post this for us to use. I will try to implement this in one of my programs or something.

  77. Spent a couple of days trying to get my head around this area and this is simply THE best starter tutorial that exists!!