Test Driven Development in .NET Part 9: advanced topics in the Moq framework

In this post we’ll continue our discussion on the Moq framework. We’ll look at the following topics:

  • Strict mocking
  • Mocking base classes
  • Recursive mocking
  • Mock Repository

We’ll build on the test suite we’ve working on in this series on Moq. This is the last post dedicated to Moq in the TDD series.

Strict and loose mocking

Strict mocking means that we must set up expectations on all members of a mock object otherwise an exception is thrown. Loose mocking on the other hand does not require explicit expectations on all class members; instead default values are returned when no expectation is explicitly declared.

Default behaviour in Moq is loose coupling.

To demonstrate strict mocking locate the call to _productRepository.Save in ProductService.Create. Let’s say that for whatever reason we make another call on _productRepository right after Save:

_productRepository.Fetch();

Have VS create the method stub for you. Run the tests and they should all pass. Go to the test called Then_repository_save_should_be_called() in When_creating_a_product.cs. We set up one expectation on the product repository, that is the Save method must be called. VerifyAll will verify that our expectations are met and ignores all other things. It does not care that we call Fetch after Save in the Create method and this is due to loose mocking. If there’s no expectation on Fetch, then it is ignored. If you want to change the behaviour to strict mocking then it’s very easy to do:

var mockProductRepository = new Mock<IProductRepository>(MockBehavior.Strict);

Run the tests and Then_repository_save_should_be_called() will fail. The exception thrown reads as follows: IProductRepository.Fetch() invocation failed with mock behavior Strict. Moq saw an interaction with the customer repository that was not set up properly so it threw an exception.

Base class mocking

We often have base classes for related objects where common behaviour and abstract properties and methods are contained in the base. We want to be able to verify that the derived classes made the call to a method or property in the abstract class.

We want the customer to go through an initial property setting phase. This action will be performed through an abstract base class called PropertySetterBase. Open When_creating_a_product.cs and add a new method called Then_initial_properties_should_be_set() with the following Arrange and Act sections:

[Test]
		public void Then_initial_properties_should_be_set()
		{
			//Arrange
			Mock<ProductPropertySetter> productPropertySetter = new Mock<ProductPropertySetter>();
			Product product = new Product("ProductA", "High qualitiy product");

			//Act
			productPropertySetter.Object.SetBasicProperties(product);

		
		}

Let VS create the missing classes and methods for you a we saw in previous blog posts in this series. As we said we want to verify that a certain method is called in the base class of the ProductPropertySetter object.

Note that we create a mock of the object that we want to test. It is not some interface dependency we want to mock but the system under test itself. The Object property will then yield the implementation of the mocking. Finally we call the SetBasicProperties on the mock object.

Add the following assertion:

//Assert
productPropertySetter.Verify(x => x.SetProperties(product));

This time do not let VS create the method for you as it will insert it in the ProductPropertySetter class. Instead insert an abstract class called PropertySetterBase in the Domain layer and have ProductPropertySetter derive from it. Insert a method called SetProperties in PropertySetterBase which accepts a Product object. This should get rid of the compiler error.

Run the tests and the new test method will fail of course as SetBasicProperties is not implemented yet. Let’s implement it as follows:

public void SetBasicProperties(Product product)
		{
			SetProperties(product);
		}

Run the tests… …you should still see that the new test method fails. Remember the problem we had in the previous post, that we had to help Moq with the ‘virtual’ keyword? We have the same case here. Insert the ‘virtual’ keyword in the signature of the SetProperties method and then the test will pass.

Recursive mocking

We looked at recursive mocking in this post where we looked at how mock a chain of properties. There’s another form of recursive mocking: say that a class has a dependency which then creates another dependency within one of the class methods. A classic example is a factory that builds some other object based on some inputs. This other object is then an indirect dependency which the class uses in some way. We would like to be able to verify that the appropriate method of the dependency injected by the factory was called.

It’s time to create a new domain object, I don’t want to expand Product and Customer even more. The new domain is called Shop and it will have an Address object property. The address will be created using a factory. Add a new folder called Shop_Tests in the Tests layer and a new file called When_creating_a_new_shop.cs in that folder:

[TestFixture]
	public class When_creating_a_new_shop
	{
		[Test]
		public void The_address_should_be_created()
		{

		}
	}

In order to create a new ship we’ll need to have a ShopService that accepts an AddressFactory and a ShopRepository. So let’s mock them up:

//Arrange
			Mock<IShopRepository> mockShopRepository = new Mock<IShopRepository>();
			Mock<IAddressFactory> mockAddressFactory = new Mock<IAddressFactory>() { DefaultValue = DefaultValue.Mock };
			ShopService shopService = new ShopService(mockShopRepository.Object, mockAddressFactory.Object);

This all should be quite straighforward by now except for the ‘DefaultValue = DefaultValue.Mock’ bit. When we set up the address factory we set the default value on it to return a mock. So if we don’t have a setup for any of the properties or the return values on this address factory it is going to return back a mock instance of whatever value it should be if it can. The address factory will return some concrete class and by providing the DefaultValue of Mock Moq will try to mock the returned concrete object coming out from the factory – as long as the return value is mockable. As we’re planning to build an abstract factory, i.e. the return type is another interface, that should be no problem. Add the following to the Assert section:

IAddressCreator addressCreator = mockAddressFactory.Object.CreateFrom(It.IsAny<string>());

This syntax should be clear by now: the address factory will have a CreateFrom method that accepts a string and returns an IAddressCreator. As usual, let VS create the missing elements for you. We’re getting hold of the address creator to be able to set up our expectations on it. The result is an IAddressFactory, but we need to get hold of the mock object, so add one more line to Arrange:

Mock<IAddressCreator> mock = Mock.Get(addressCreator);

Next we’ll do some action:

//Act
shopService.Create(new Shop());

The address of the shop will be built using the IAddressCreator. This interface will have a method called CreateAddressFor which accepts a Shop object. We want to assert that this CreateAddressFor method was called:

//Assert
mock.Verify(x => x.CreateAddressFor(It.IsAny<Shop>()));

Run the tests and as usual this new test should fail, which is good. Implement ShopService.Create as follows:

public void Create(Shop shop)
		{
			IAddressCreator addressCreator = addressFactory.CreateFrom("USA");
			Address address = addressCreator.CreateAddressFor(shop);
			shop.Address = address;
			shopRepository.Save(shop);
		}

Create the missing objects and methods using Visual Studio. The test should pass meaning that we successfully verified that the CreateAddressFor method was called on a dependency injected by the factory which in turn was also injected in the constructor.

Using the MockRepository to handle a lot of dependencies

At times you may be dealing with a lot of dependencies of an object. Many dependencies can point to different problems, such as the object is trying to achieve too much, but that’s beside the point here.

It is tedious to write setups and verifications on each dependency. The MockRepository object makes handling a large number of dependencies easier. We’ll return to the When_creating_a_product.cs class. Insert a new test method which is an updated version of Then_repository_save_should_be_called():

[Test]
		public void Then_repository_save_should_be_called_MOCK_REPO()
		{
			//Arrange
			MockRepository mockRepository = new MockRepository(MockBehavior.Loose) { DefaultValue = DefaultValue.Mock };
			Mock<IProductRepository> productRepository = mockRepository.Create<IProductRepository>();
			Mock<IProductIdBuilder> productIdBuilder = mockRepository.Create<IProductIdBuilder>();
			productRepository.Setup(p => p.Save(It.IsAny<Product>()));
			ProductService productService = new ProductService(productRepository.Object, productIdBuilder.Object);

			//Act
			productService.Create(new ProductViewModel());
			//Assert
			mockRepository.Verify();

		}

We initialise a new MockRepository and we indicate the mock behaviour and the default value. These will be valid for all mock objects created by the repository, you don’t need to specify them one by one. Next we create the mocked dependencies for the ProductService using the mock repository directly. At the end we call the Verify method on the mock repository. This is a short-hand solution instead of calling Verify on each and every expectation we set up. The mock repository will go through each mock element and run the verifications accordingly.

Protected members

In some cases you may want to test that a protected member of a class was called. This is not a straightforward scenario as protected members are not available outside the class. Moq can solve the problem but it comes with some ‘buts’: there’s no intellisense as protected members are invisible; instead they must be referred to using strings. Also, instead of the ‘It’ keyword ‘ItExpr’ must be used. In addition, the protected member under test must be marked with the virtual keyword as we saw in previous examples.

You’ll need to include the Moq.Protected namespace with a using statement. An example of setting up our expectations on a protected member is the following:

mockIdBuilder.Protected().Setup<string>("GetResult", ItExpr.IsAny<string>())
				.Returns("hello").Verifiable();

The Protected() extension method is the gateway to testing a protected member. Setup denotes the return type of the protected member. “GetResult” is the name of protected method under test and it is followed by the parameters the method accepts using the ItExpr method: in this case the imaginary GetResult method accepts one parameter of type string. We set up the method to return the string “hello” and mark it as Verifiable. If you miss this step then Moq will not be able to check if this expectation has been met. It does not make any difference if you call Verify in the Assert section at the end, the setup of a protected member must be marked as verifiable.

This ends our discussion of the Moq framework. I hope you now know enough to start writing your own mock objects in your tests.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Test Driven Development in .NET Part 9: advanced topics in the Moq framework

  1. Atilla Selem says:

    very good Andras..very good..all ur efforts are appreciated 🙂

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 )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: