TDD : Introduction to Moq

In this post, I provide an introduction to Moq which is the newest of the Mock Object Frameworks. Moq is promoted by its creators as easier to learn and use than other Mock Object Frameworks such as Rhino Mocks and TypeMock Isolator.

Moq takes advantage of recent VB.NET and C# language features such as lambdas and generics. When creating mock objects with Moq, you use lambda expressions to represent the methods and properties that you want to mock. The emphasis on lambdas enables Moq to provide a very clean syntax for representing expectations, parameter constraints, and return values.

According to the authors of Moq, you can pronounce “Moq” either like “Mock-You” or like “Mock”. The name “Moq” comes from a combination of Mock and Linq. Since Moq uses lambda expressions and not Linq, the name “Mambda” might have been more accurate.

Moq is actively maintained by Daniel Cazzulino. You can read Daniel Cazzuiono’s blog entries on Moq here:

http://www.clariusconsulting.net/blogs/kzu/archive/category/1062.aspx

This post is about Moq version 2.5.

Some Background, Some Philosophy, and Some Controversy

There is just something about Mock frameworks that generate controversy. There are now three popular Mock frameworks: Typemock Isolator, Rhino Mocks, and Moq. TypeMock Isolator has been criticized for being too powerful and Moq has been criticized for being too simple. Why the criticism?

Some people have criticized Typemock Isolator for being too powerful. The criticism is that TypeMock Isolator might encourage bad software design because it enables you to be lazy about the architecture of your code. The argument is that building mockable code should force you to write well designed code. Since Typemock Isolator enables you to mock anything and everything, the tool does not lead you down the virtuous path to code nirvana. Typemock Isolator is like giving a nuclear weapon to a four year old child.

While Typemock Isolator has been criticized for being too powerful, Moq has been criticized for being too simple. The complaint is that Moq mixes up mocking and stubbing. Understanding this criticism requires some background.

Martin Fowler wrote an interesting and influential paper entitled Mocks Aren’t Stubs which you can read here:

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

In this paper, Fowler makes several distinctions. First, he distinguishes a stub from a mock. According to Fowler -- who uses Meszaros’ definitions here – stubs “provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.” Mocks, on the other hand, are “objects pre-programmed with expectations which form a specification of the calls they are expected to receive”.

This distinction between stubs and mocks leads Fowler to distinguish between state verification and behavior verification. Stubs are most often used when performing state verification. When performing state verification, you are interested in determining whether a certain condition is true or false at the end of a test. Mocks, on the other hand, are most often used when performing behavior verification. When performing behavior verification, you are interested in how the mock objects interact. For example, you want to know whether a not a certain method was called on one mock object after a method was called on another mock object.

Fowler makes a final distinction between classical TDD and mockist TDD. This final distinction concerns the “philosophy to the way testing and design play together”. A classical TDDer tends to use stubs and state verification. According to Fowler, the “classical TDD style is to use real objects if possible and a double if it's awkward to use the real thing.” A mockist TDDer, on the other hand, almost always uses mocks and behavior verification. A mockist TDDer “will always use a mock for any object with interesting behavior.”

A classical TDDer uses a Mock Object Framework to make it easier to build unit tests. If the code that you are testing has a dependency on some other object, you can create a quick stub for the inconvenient object and continue writing your unit test. From the perspective of a classical TDDer, that is what a Mock Object Framework is for.

A mockist TDDer inhabits a completely different world. A mockist TDDer believes that the design of an application should be driven by the way that you expect objects in your application to interact. A mockist TDDer uses mock objects to pantomime the final application. Therefore, everything gets mocked in a test.

Moq has been criticized for not respecting the needs of both the classical TDDer and the mockist TDDer. Moq makes it easy to make stubs and not mocks. This is either a good thing or bad thing depending on what you want out of a Mock Object Framework.

Daniel Cazzulino, the primary author of Moq, is unapologetically a classical TDDer. There is a very interesting exchange between Daniel Cazzulino and Ayende (the author of Rhino Mocks) on this topic at:

http://www.ayende.com/Blog/archive/2007/12/19/Moq-Mocking-in-C-3.0.aspx

Daniel Cazzulino argues that most developers, if they are using Test-Driven Development at all, don’t distinguish between classical TDD and mockist TDD. And, in fact, the distinction isn’t as clear cut as Martin Fowler describes. You can read Daniel Cazzulino’s paper, entitled Mocks, Stubs and Fakes: it's a continuum by visiting Daniel Cazzulino’s blog at:

http://www.clariusconsulting.net/blogs/kzu/archive/2007/12/21/47152.aspx

Daniel Cazzulino does not use the Fowler/ Meszaros distinctions between mocks and stubs. He claims that most developers use the word “mocks” when referring to what Fowler/Meszaros would refer to as stubs and that we should respect the everyday language use of these words. Since this post in on Moq, for the remainder of this post I will knowingly and actively conflate mocks and stubs out of respect for Daniel Cazzulino.

Installing and Setting Up Moq

Moq is maintained as a Google Code project. You can download the Moq binaries and API documentation here:

http://code.google.com/p/moq/

After you download the Moq binaries from Google Code, make sure that you unblock the archive by right-clicking the file, selecting Properties, and pushing the Unblock button (see Figure 1). If you forget to do this, you run into confusing security issues when you try to use Moq within Visual Studio.

clip_image002

The archive includes an assembly named Moq.dll. You need to add this assembly to your test project in Visual Studio. You also need to add the Moq namespace to your test classes.

What Can Be Mocked?

You can use Moq to create mocks from both interfaces and existing classes. There are some requirements on the classes. The class can’t be sealed. Furthermore, the method being mocked must be marked as virtual. You cannot mock static methods (use the adaptor pattern to mock a static method).

These limitations are the same as the limitations you face when working with Rhino Mocks. Both Moq and Rhino Mocks use proxy classes under the covers. Indeed, both frameworks derive from the same Castle DynamicProxy code base.

Mocking Methods and Properties

Imagine that you are building a database-driven web application. Imagine, for example, that you are creating an online store. You want to concentrate on writing all of the business logic for your store before doing anything else. In particular, you don’t want to devote any time to writing your data access components before writing your business components.

This is a good situation to take advantage of a Mock Object Framework. In this situation, you can create an interface that describes how you want your data access component to look. Then, you can simply mock the interface and take advantage of the mock while testing your business logic. The mock enables you to avoid writing code until you are really ready to do it.

The first interface in Listing 1, named IProductRepository, represents two methods. The first method, Select(), returns all of the products from the database. The second method, Get(), returns a particular product by matching the product’s Id. Listing 1 also contains an interface, named IProduct, that represents a particular product.

Listing 1 – IProductRepository.cs

   1: using System;
   2: using System.Collections.Generic;
   3:  
   4: namespace MoqSamples.Models
   5: {
   6:     public interface IProductRepository
   7:     {
   8:         List<IProduct> Select();
   9:         IProduct Get(int id);
  10:     }
  11:  
  12:     public interface IProduct
  13:     {
  14:         int Id {get; set;}
  15:         string Name { get; set; }
  16:     }
  17: }

Let’s start with mocking the IProduct interface. The following code creates a product that has an Id property with the value 1 and a Name property with the value “Bushmills”:

   1: // Mock a product
   2: var newProduct = new Mock<IProduct>();
   3: newProduct.ExpectGet(p => p.Id).Returns(1);
   4: newProduct.ExpectGet(p => p.Name).Returns("Bushmills");

The first line of code creates the mock from the IProduct interface. The Mock class is a class from the Moq framework. The Mock class has a generic constructor that accepts the type of the interface to create.

Next, the Id property is setup to return the value 1 and the Name property is setup to return the value “Bushmills”. Notice how lambda expressions are used to represent the Id and Name property. The advantage of using a lambda expression to represent a property instead of a string is that refactoring tools such as Resharper can refactor the properties automatically.

After you create the mock newProduct, you can use the mock just as if you had actually implemented the IProduct interface. For example, the following Assert executes successfully:

Assert.AreEqual("Bushmills", newProduct.Object.Name);

Notice that you must use newProduct.Object when referring to the mock newProduct. The newProduct variable represents the proxy class and the newProduct.Object variable represents the actual newProduct class.

Now let’s mock the IProductRepository interface. The following lines of code create a mock IProductRepository that returns newProduct when its Get() method is called:

   1: // Mock product repository
   2: var productRepository = new Mock<IProductRepository>();
   3: productRepository
   4:    .Expect(p => p.Get(1))
   5:    .Returns(newProduct.Object);

The first line of code creates the mock by passing IProductRepository to the Mock class’s generic constructor. The next line setups the Get() method to return the mock newProduct. Notice that the Get() method call is represented with a lambda.

After you create IProductRepository mock, you can use it in your tests like this:

   1: // Act
   2:  
   3: var productReturned = productRepository.Object.Get(1);
   4:  
   5: // Assert
   6:  
   7: Assert.AreEqual("Bushmills", productReturned.Name);
   8:  

When you call the Get() method with the value 1, the newProduct object is returned. If you call Get() with any other value than 1 then a Null value is returned. If you want the Get() method to return newProduct regardless of the argument passed to the Get() method, then you can create the mock IProductRepository with the following lines of code:

   1: // Mock product repository
   2: var productRepository = new Mock<IProductRepository>();
   3: productRepository
   4:   .Expect(p => p.Get(It.IsAny<int>()))
   5:   .Returns(newProduct.Object);

Notice that the It.IsAny<int>() constraint is passed to the Get() method when setting up the method expectation. This argument causes the mock Get() method to accept any integer value and return the newProduct object.

You can even specify fancy custom constraints by taking advantage of a lambda expression. Consider the following code:

   1: // Mock product repository
   2: var productRepository = new Mock<IProductRepository>();
   3: productRepository
   4:    .Expect(p => p.Get(It.Is<int>(id => id>0 && id<6)))
   5:    .Returns(newProduct.Object);

This code returns the newProduct object only when the id parameter passed to the Get() method has a value between 0 and 6. This constraint is specified within a lambda expression passed to the It.Is() method.

Moq is Mockist Friendly (At Least a Little Bit)

The Moq framework can be used to perform limited behavior verification. For example, you can use Moq to detect whether a particular method was called at least once after calling another method.

Moq’s support for behavior verification is limited. Unlike other Mock Object Frameworks, such as Rhino Mocks and Typemock Isolator, you cannot use Moq to test complex interactions between objects. Moq does not support the same kind of record and replay code blocks supported by Rhino Mocks and Typemock Isolator.

When would you want to perform behavior verification? Martin Fowler provides the example of a memory cache. He writes “The whole point of a cache is that you can't tell from its state whether the cache hit or missed - this is a case where behavior verification would be the wise choice for even a hard core classical TDDer” (quotation is from Mocks Aren’t Stubs).

Imagine that you have implemented a ProductRepository class and that the class includes a method named GetProduct() that retrieves a product. The method first attempts to get the product from the cache. If the method is not successful then the method retrieves the product from the database. The ProductRepository class is contained in Listing 2:

Listing 2 – ProductRepository

   1: using System;
   2: using System.Web;
   3:  
   4: namespace MoqSamples.Models
   5: {
   6:     public class ProductRepository : IProductRepository
   7:     {
   8:         private ProductCache _cache;
   9:  
  10:         public ProductRepository(ProductCache cache)
  11:         {
  12:             _cache = cache;
  13:         }
  14:  
  15:         public virtual IProduct GetProduct(int id)
  16:         {
  17:             var product = _cache.Get(id);
  18:             if (product == null)
  19:             {
  20:                 product = this.Get(id);
  21:                 _cache.Set(id, product);
  22:             }
  23:             return product;
  24:         }
  25:         
  26:         public virtual IProduct Get(int id)
  27:         {
  28:             throw new NotImplementedException();
  29:         }
  30:  
  31:         public System.Collections.Generic.List<IProduct> Select()
  32:         {
  33:             throw new NotImplementedException();
  34:         }
  35:  
  36:     }
  37: }

A ProductCache object is passed to the ProductRepository class through construction dependency injection. The ProductRepository GetProduct() method first attempts to grab a product from this cache object and, if it fails, it calls the Get() method to grab the product from the database. Notice that I haven’t bothered to implement the Get() method. That’s okay since we will be mocking it anyway.

The ProductCache class is a strongly typed wrapper around the normal ASP.NET System.Web.Caching.Cache object. The code for the ProductCache is contained in Listing 3:

Listing 3 – ProductCache.cs

   1: using System;
   2: using System.Web;
   3:  
   4: namespace MoqSamples.Models
   5: {
   6:     public class ProductCache
   7:     {
   8:         public virtual IProduct Get(int id)
   9:         {
  10:             return (IProduct)HttpContext.Current.Cache["product_" + id];
  11:         }
  12:  
  13:         public virtual void Set(int id, IProduct product)
  14:         {
  15:             HttpContext.Current.Cache["product_" + id] = product;
  16:         }
  17:     }
  18: }

Notice that both methods of the ProductCache class are marked as virtual. You must mark methods as virtual when you want to be able to mock them.

We can test whether the ProductCache is used correctly by taking advantage of Moq when creating a unit test. The unit test in Listing 4 demonstrates how to use Moq to perform simple behavior verification:

Listing 4 – ProductTest.cs

   1: using System;
   2: using Microsoft.VisualStudio.TestTools.UnitTesting;
   3: using MoqSamples.Models;
   4: using Moq;
   5: using System.Web;
   6:  
   7: namespace MoqSamplesTests
   8: {
   9:     [TestClass]
  10:     public class ProductTest
  11:     {
  12:         [TestMethod]
  13:         public void TestCache()
  14:         {
  15:             // Setup
  16:             var mockCache = new Mock<ProductCache>();
  17:             var mockProducts = new Mock<ProductRepository>(mockCache.Object);
  18:             var mockProduct = new Mock<IProduct>();
  19:  
  20:             // Expectations
  21:             mockCache
  22:                 .Expect(c => c.Get(1))
  23:                 .Returns<IProduct>(null)
  24:                 .Verifiable(); // No product in cache
  25:  
  26:             mockProducts
  27:                 .Expect(p => p.Get(1))
  28:                 .Returns(mockProduct.Object)
  29:                 .Verifiable(); // Get product from db
  30:  
  31:             mockCache
  32:                 .Expect(c => c.Set(1, mockProduct.Object))
  33:                 .Verifiable(); // Set product in cache
  34:  
  35:             // Reality
  36:             var product = mockProducts.Object.GetProduct(1);
  37:  
  38:             // Assert
  39:             mockProducts.Verify(); 
  40:             mockCache.Verify();  
  41:         }
  42:  
  43:     }
  44: }

In Listing 4, the setup section is used to setup three mock objects: mockCache, mockProducts, and mockProduct. Next, in the expectations section, expectations are created that represent how the methods of these mock objects are expected to be called. Notice that all three expectations include a call to a method named Verifiable(). When the Verify() method is called at the end of the test, if any of the expectations marked as verifiable have not been called, then an exception is thrown.

The test in Listing 4 checks that the following expectations are met when the GetProduct() method is called:

· The ProductCache.Get() method is called

· The ProductRepository.Get() method is called

· The ProductCache.Set() method is called

In other words, when the GetProduct() method is first called, we want to make sure that the product being requested is added to the cache.

Again, it is important to emphasize the limitations of Moq here. You can’t use Moq to verify whether or not these methods were called in a particular order or a particular number of times. Moq is good at state verification and not behavior verification.

Conclusion

I like Moq. I like how Moq takes advantage of lambdas when building expectations. I find this aspect of the framework very intuitive. If you are a classical TDDer then I think that you will discover a lot to like in Moq.

If you need to mock objects that cannot be handled by Moq, such as static methods or sealed classes, then you should consider using Typemock Isolator. If you are working with legacy code, then you might not have the luxury of working with a well-designed, loosely coupled application. In that case, Typemock Isolator might be your only viable choice.

Finally, if you lean more towards mockist TDD than classical TDD, then you will find Rhino Mocks more appealing. Rhino Mocks provides a richer framework for performing behavior verification.

5 Comments

Comments have been disabled for this content.