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

Test Driven Development in .NET Part 8: verify class properties with mocks using the Moq framework

So far in this series on Moq we’ve been concentrating on mocking methods, their return values and exceptions they may throw. However, we should not forget about object properties: setters and getters. Writing tests may become quite involved when we need to set up a hierarchy of properties: a property of an object is another object which has a property that is also an object which has a property etc.

The demos build on the project where we left off in the previous post.

Setters

The most basic test we can perform is check if a property has been assigned a value, i.e. the property setter has been called. We’ll add a property to ICustomerRepository called LocalTimeZone and see if that setter has been called when creating a new Customer.

Open the solution we’ve been working with in this series on Moq. Add a new class called When_creating_a_customer to the CustomerService_Tests folder and insert the following test skeleton:

[TestFixture]
    public class When_creating_a_customer
    {
        [Test]
        public void The_local_timezone_should_be_set()
        {
            //Arrange
            Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
            Mock<ICustomerStatusFactory> mockCustomerStatusFactory = new Mock<ICustomerStatusFactory>();
            CustomerViewModel customerViewModel = new CustomerViewModel()
            {
                FirstName = "Elvis"
                , LastName = "Presley"
                , Status = CustomerStatus.Gold
            };
            CustomerService customerService = new CustomerService(mockCustomerRepository.Object, mockCustomerStatusFactory.Object);
                        
            //Act
            customerService.Create(customerViewModel);
        }
    }

This should be familiar from the discussions in the previous post. What we’re missing is the Assert section:

//Assert
mockCustomerRepository.VerifySet(c => c.LocalTimeZone = It.IsAny<string>());

VerifySet means that we want to verify that a setter has been called. We specify which setter we mean by the lambda expression. Let VS create the property stub for LocalTimeZone. The new test should fail as we do not set this property in the Create method. Let’s modify it now:

public void Create(CustomerViewModel customerToCreate)
        {
            var customer = new Customer(
                customerToCreate.FirstName, customerToCreate.LastName);

            customer.StatusLevel =
                _customerStatusFactory.CreateFrom(customerToCreate);
            _customerRepository.LocalTimeZone = TimeZone.CurrentTimeZone.StandardName;
            if (customer.StatusLevel == CustomerStatus.Gold)
            {
                _customerRepository.SaveSpecial(customer);
            }
            else
            {
                _customerRepository.Save(customer);
            }
        }

The test should now pass along with all the other tests.

Getters

We want to be able to update a customer. The Customer object will receive a new property called RegionId which will be set using a getter of the ICustomerRepository interface. We want to make sure that this getter has a value, i.e. is not null.

Add a new class to CustomerService_Tests called When_updating_a_customer with the following starting point for a test:

[TestFixture]
    public class When_updating_a_customer
    {
        [Test]
        public void The_region_id_of_repository_should_be_used()
        {
            //Arrange
            Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
            Mock<ICustomerStatusFactory> mockCustomerStatusFactory = new Mock<ICustomerStatusFactory>();
            CustomerViewModel customerViewModel = new CustomerViewModel()
            {
                FirstName = "Elvis"
                ,LastName = "Presley"
                ,Status = CustomerStatus.Gold
            };
            CustomerService customerService = new CustomerService(mockCustomerRepository.Object, mockCustomerStatusFactory.Object);

            //Act
            customerService.Update(customerViewModel);
        }

    }

Note the addition of the Update method, let VS create it for you.

Add the following setup statement just before the construction of the CustomerService object:

mockCustomerRepository.Setup(c => c.RegionId).Returns(123);

This looks very much like setting up the return value of a method. Let VS take care of the RegionId property. Make sure the generated property is of type nullable integer. We’re missing the Assert statement:

//Assert
            mockCustomerRepository.VerifyGet(x => x.RegionId);

VerifyGet – as you may have guessed – means that we want to make sure that a getter was called. The getter is then defined by the lambda expression. Run the test and as usual the new one should fail. Let’s implement the Update method:

public void Update(CustomerViewModel customerViewModel)
        {
            var customer = new Customer(
                customerViewModel.FirstName, customerViewModel.LastName);
            int? regionId = _customerRepository.RegionId;
            if (!regionId.HasValue)
            {
                throw new InvalidRegionIdException();
            }
            customer.RegionId = regionId.Value;
            _customerRepository.Update(customer);
        }

As usual, let VS take care of the missing elements. The test should now pass.

Mocking property hierarchies

One extra scenario we must consider is when a dependency returns a deeply nested property and we want to access the end of the nested property chain. Example: the Settings property of a Customer is returned as follows:

customer.Settings = _customerRepository.SystemConfig.BaseInformation.Settings;

This is exactly what we want to achieve. Open When_creating_a_customer.cs and insert a new test method called The_customer_settings_should_be_retrieved(). Arrange and Act will be familiar:

//Arrange
			Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
			Mock<ICustomerStatusFactory> mockCustomerStatusFactory = new Mock<ICustomerStatusFactory>();
			CustomerViewModel customerViewModel = new CustomerViewModel()
			{
				FirstName = "Elvis"
				,LastName = "Presley"
				,Status = CustomerStatus.Gold
			};
			CustomerService customerService = new CustomerService(mockCustomerRepository.Object, mockCustomerStatusFactory.Object);

			//Act
			customerService.Create(customerViewModel);

We only need to include the Assert phase now. We want to assert that the Settings property has been retrieved:

mockCustomerRepository.VerifyGet(x => x.SystemConfig.BaseInformation.Settings);

Create the necessary classes and properties. Don’t worry about the implementations. Run the tests and the new test will fail as usual. Go to CustomerService.Create and include the following call just below _customerStatusFactory.CreateFrom:

customer.Settings = _customerRepository.SystemConfig.BaseInformation.Settings;

Run the tests and 3 of them should fail:

Tests fail when testing for nested properties

We forgot to properly set up the expectations on the nested properties so they all return null causing a null reference exception to be thrown. Include the following Setup in the Arrange section:

                                mockCustomerRepository
				.Setup(x => x.SystemConfig.BaseInformation.Settings)
				.Returns(new Settings());

Run the tests again and you’ll see that we still have the previous 3 failing methods. However, the error message on the test we’re currently working on is different: invalid setup on a non-virtual member. It turns out that this is due to Moq, not our code really. Moq can make it easy to mock up a chain of nested properties like that but it needs some help. The solution is to mark the properties in that chain with the ‘virtual’ keyword to let Moq know it is a mockable property:

public class SystemConfig
	{
		public virtual BaseInformation BaseInformation { get; set; }
	}

public class BaseInformation
	{
		public virtual Settings Settings { get; set; }
	}

public class Settings
	{
		public virtual string Colour { get; set; }
	}

Another solution would be to turn BaseInformation, Settings and SystemConfig properties to interfaces, but I think in this case it would be wrong. They are object properties, not interfaces.

This is the trade-off. In other mocking frameworks you may need to set up the expectations on each nest property one by one. Moq makes our lives easier by mocking up each property in the chain for us, but in turn we need to add the ‘virtual’ modifier. Run the tests and the current one should pass. Add the same setup to the other two failing tests as well.

Stubbing properties

There are occasions where a dependency has many properties that need to be set up. It is tedious to call a Setup on each. Instead we can instruct Moq to create a stub of the dependency as opposed to a mock. Stubbing is performed via the SetupAllProperties method:

mockCustomerRepository.SetupAllProperties();
mockCustomerRepository.Object.SystemConfig = new SystemConfig();

After calling SetupAllProperties we can set the value of each property as shown in the example.

In the next post we’ll investigate some more advanced features of this mocking framework.

Test Driven Development in .NET Part 7: verify method arguments and exceptions with mocks using the Moq framework

In this post we’ll discuss how to verify arguments and exceptions using Moq.

Arguments

Arguments to our mock objects are important components. Therefore we should verify that the correct input parameters were passed to them. This will ensure that the right input data is used by the dependency injected into the system under test. Different parameters will also enable to us to check the behaviour of the system, e.g. by controlling the execution flow.

Open the solution we worked on in the previous post. The domain experts say that the product ID should be somehow built based on the product name. We want to extend the IProductIdBuilder interface with an overloaded BuildProductIdentifier method that accepts the Name of the product. Then we want to verify that the input parameter passed to this method is valid.

Locate When_creating_a_product.cs and add the following test:

[Test]
        public void The_product_id_should_be_created_from_product_name()
        {

        }

The Arrange phase look as follows:

//Arrange
            ProductViewModel productViewModel = new ProductViewModel() { Description = "Nice product", Name = "ProductA" };
            Mock<IProductRepository> mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            mockIdBuilder.Setup(i => i.BuildProductIdentifier(It.IsAny<String>()));
            ProductService productService = new ProductService(mockProductRepository.Object
                , mockIdBuilder.Object); 

Note the String parameter passed to BuildProductIdentifier. Let Visual Studio create the overloaded method in the IProductIdBuilder interface. If you recall from the first post on Moq this type of setup will help verify that the BuildProductIdentifier method was called when the Create method in ProductService.cs is called.

Act is simple:

//Act
productService.Create(productViewModel);

Assert is a bit more complicated:

//Assert
mockIdBuilder.Verify(m => m.BuildProductIdentifier(It.Is<String>(n => n.Equals(productViewModel.Name, StringComparison.InvariantCultureIgnoreCase))));

Here we say that in the BuildProductIdentifier method we want to check that the parameter passed into it will be the same as the Name property of the product.

Run the tests and this new test should fail. Look at the reason in the Test Explorer window: an InvalidProductIdException was thrown. Of course we forgot to set up the expected return value of the BuildProductIdentifier method. Go ahead and replace the Setup as follows:

mockIdBuilder.Setup(i => i.BuildProductIdentifier(It.IsAny<String>())).Returns(new ProductIdentifier());

Re-run the tests and… …our new test still fails with the same message. Can you guess why? There are now two methods in IProductIdBuilder and the current Setup sets up the overloaded method whereas the current implementation of the Create method in ProductService uses the parameterless version which will return a null object. So we must pass in the product name to BuildProductIdentifier in the Create method:

product.Identifier = _productIdBuilder.BuildProductIdentifier(product.Name);

Re-run the tests and you’ll see that the new test passes but we have two failing ones: The_product_should_be_saved_if_id_was_created() and Then_repository_save_should_be_called(). The reason is the same as above: we’re setting up the wrong BuildProductIdentifier method now that we have the new policy of creating the ID from the product name. I hope you’re starting to see the real power of TDD.

Adjust the setup method in Then_repository_save_should_be_called() as follows:

mockIdBuilder.Setup(x => x.BuildProductIdentifier(It.IsAny<string>())).Returns(new ProductIdentifier());

And in The_product_should_be_saved_if_id_was_created():

mockIdBuilder.Setup(i => i.BuildProductIdentifier(productViewModel.Name)).Returns(new ProductIdentifier());

The tests should now pass.

You can even test the new test method by passing in the Description property of the Product object to BuildProductIdentifier in the Create method of ProductService. The test will fail because the expected Name property does not equal the actual value passed in.

Controlling the flow of execution

For the flow control demo we’ll work with a new object in our domain: Customer. The domain experts say that Customers must have a first and last name and should have a Status. The developers then translate the requirements into a simple code-branching mechanism when a new Customer needs to be saved: either save it ‘normally’ or in some special way depending on the customer status.

As usual we’ll take a test-first approach. Add a new folder to the Tests project called CustomerService_Tests. Add a new class called CustomerServiceTests to that folder with the first test method looking like this:

[TestFixture]
    public class When_creating_a_gold_status_customer
    {
        [Test]
        public void A_special_save_routine_should_be_used()
        {

        }
    }

We know that we’ll need some type of Repository to save the customer and also a factory that will yield the appropriate Status type based on some parameters. Insert the following Arrange section:

//Arrange
            Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
            Mock<ICustomerStatusFactory> mockCustomerStatusFactory = new Mock<ICustomerStatusFactory>();
            CustomerViewModel customerViewModel = new CustomerViewModel()
            {
                FirstName = "Elvis"
                , LastName = "Presley"
                , Status = CustomerStatus.Gold
            };

            CustomerService customerService = new CustomerService(mockCustomerRepository.Object, mockCustomerStatusFactory.Object);

Create the missing objects, constructors etc. using Visual Studio. Make sure that CustomerStatus is created as an enum type. In Act we’ll call the Create method:

//Act
customerService.Create(customerViewModel);

In the assert phase we want to verify that the SaveSpecial method is called:

//Assert
mockCustomerRepository.Verify(
                x => x.SaveSpecial(It.IsAny<Customer>()));

The test will of course fail at first so we’ll fill up our newly created objects:

Customer.cs:

public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public CustomerStatus StatusLevel { get; set; }

        public Customer(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }

CustomerStatus:

public enum CustomerStatus
    {
        Bronze,
        Gold,
        Platinum
    }

CustomerViewModel:

public class CustomerViewModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public CustomerStatus Status { get; set; }
    }

ICustomerRepository:

public interface ICustomerRepository
    {
        void SaveSpecial(Customer customer);
        void Save(Customer customer);
    }

ICustomerStatusFactory:

public interface ICustomerStatusFactory
    {
        CustomerStatus CreateFrom(CustomerViewModel customerToCreate);
    }

CustomerService:

public class CustomerService
    {
        private readonly ICustomerRepository _customerRepository;
        private readonly ICustomerStatusFactory _customerStatusFactory;

        public CustomerService(ICustomerRepository customerRepository, ICustomerStatusFactory customerStatusFactory)
        {
            _customerRepository = customerRepository;
            _customerStatusFactory = customerStatusFactory;
        }

        public void Create(CustomerViewModel customerToCreate)
        {
            var customer = new Customer(
                customerToCreate.FirstName, customerToCreate.LastName);

            customer.StatusLevel =
                _customerStatusFactory.CreateFrom(customerToCreate);

            if (customer.StatusLevel == CustomerStatus.Gold)
            {
                _customerRepository.SaveSpecial(customer);
            }
            else
            {
                _customerRepository.Save(customer);
            }
        }
    }

Re-run the tests and this new test still fails. We forgot to tell Moq that ICustomerStatusFactory should return the Gold status. Add the following the Arrange section of the test method:

mockCustomerStatusFactory.Setup(
                c => c.CreateFrom(It.Is(u => u.Status == CustomerStatus.Gold)))
                .Returns(CustomerStatus.Gold);

This means that if the Status of the CustomerViewModel is Gold then the CreateFrom of the mock object should return Gold. Run the test and you’ll see that indeed the SaveSpecial route is taken and the test passes.

Mocking exceptions

We can set up the dependencies so that they throw some specific exception when invoked. This way you can test how the system under test behaves when it encounters an exception from a dependency. We’ll simulate the following: we want the IProductIdBuilder dependency throw an exception and check if the exception is handled correctly.

Open When_creating_a_product.cs and add a new test method:

[Test]
        public void An_exception_should_be_raised_when_id_is_invalid()
        {

        }

Add the following skeleton to the method body:

//Arrange
            ProductViewModel productViewModel = new ProductViewModel() { Description = "Nice product", Name = "ProductA" };
            Mock<IProductRepository> mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            mockIdBuilder.Setup(i => i.BuildProductIdentifier(It.IsAny<String>())).Returns(new ProductIdentifier());
            ProductService productService = new ProductService(mockProductRepository.Object
                , mockIdBuilder.Object); 

            //Act
            productService.Create(productViewModel);
            //Assert

This code should be familiar by now.

We want an exception to be thrown if the ID is incorrect. Add the following attribute to the method:

[ExpectedException(typeof(ProductCreatedException))]
        public void An_exception_should_be_raised_when_id_is_invalid()

Let VS create the ProductCreatedException class for you. Go ahead and make the new class inherit from Exception. Next we want to set up IProductIdBuilder so that it throws an ProductIdNotCreatedException when it’s called. Replace the current Setup call with the following:

mockIdBuilder.Setup(m => m.BuildProductIdentifier(It.IsAny<string>())).Throws<ProductIdNotCreatedException>();

Again, let VS create ProductIdNotCreatedException for you and have it extend the Exception object.

This should be clear: we don’t want the BuildProductIdentifier to return an ID but to throw an exception instead. Run the tests and the new test will obviously fail. The Create method does not throw any exception when there’s an unhandled exception throws from BuildProductIdentifier. Modify the Create method as follows:

public void Create(ProductViewModel productViewModel)
        {
            try
            {
                Product product = ConvertToDomain(productViewModel);
                product.Identifier = _productIdBuilder.BuildProductIdentifier(product.Name);
                if (product.Identifier == null)
                {
                    throw new InvalidProductIdException();
                }
                _productRepository.Save(product);
            }
            catch (ProductIdNotCreatedException e)
            {
                throw new ProductCreatedException(e);
            }
        }

Let VS insert a new constructor for ProductCreatedException and run the tests. They should all pass.

In the next post we’ll take a look at how to verify class properties with Moq.

Test Driven Development in .NET Part 6: verifying return values with mocks using the Moq framework

We will continue our discussion of mocking objects using the Moq framework. You can check out the absolute basics in the previous post.

In this post we’ll look at how we can test the return values of a dependency used within the system under test. We will extend our Product domain with a new property and we’ll let a dependency handle the construction of this new property. This property will be a unique ID. The expected behaviour is that if the ID is null then the Product creation logic should throw an exception. We’ll continue with the test-first approach.

Open the solution we started building in the previous post. Locate the When_creating_a_product.cs file. Add a new test method called An_exception_should_be_thrown_if_id_is_not_created():

        [Test]
        public void An_exception_should_be_thrown_if_id_is_not_created()
        {

        }

We’ll start with the Arrange phase:

        //Arrange
            ProductViewModel productViewModel = new ProductViewModel() { Description = "Nice product", Name = "ProductA" };
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            Mock<IProductRepository> mockProductRepository = new Mock<IProductRepository>();

The concrete class that builds the ID must implement the IProductIdBuilder interface. Go ahead and let Visual Studio create the interface using the built-in techniques. Make sure it is created in the Domain project.

There is a special method attribute in NUnit which declares that we’re expecting an exception to be thrown. If the exception is thrown then the test passes. So decorate the method as follows:

        [Test]
        [ExpectedException(typeof(InvalidProductIdException))]
        public void An_exception_should_be_thrown_if_id_is_not_created()

Let VS create the InvalidProductIdException class for you. Add the following two lines to the test method body:

            ProductService productService = new ProductService(mockProductRepository.Object);

            //Act
            productService.Create(productViewModel);

Run the tests now and you should see that the new test fails as it doesn’t throw any exception. Let’s carry on with the implementation: we now know that the ProductService will need a dependency of type IProductIdBuilder:

            ProductService productService = new ProductService(mockProductRepository.Object
                , mockIdBuilder.Object);

Extend the IProductIdBuilder interface with the following method:

            public interface IProductIdBuilder
    {
        ProductIdentifier BuildProductIdentifier();
    }

Create the ProductIdentifier object with VS and add it to the property list of the Product object:

      public class Product
    {
        public ProductIdentifier Identifier { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        public Product(string name, string description)
        {
            Name = name;
            Description = description;
        }
    }      

Re-run the tests just to see if anything has broken: we get the same failing test as before.

Open InvalidProductIdException.cs and have the class derive from Exception:

public class InvalidProductIdException : Exception
    {
    }

Finally go to ProductService where we need to look at a couple of things. Now we have two constructors. Rewrite the auto-created parameter names as follows:

private IProductRepository _productRepository;
        private IProductIdBuilder _productIdBuilder;

        public ProductService(IProductRepository productRepository)
        {
            // TODO: Complete member initialization
            _productRepository = productRepository;
        }

        public ProductService(IProductRepository productRepository, IProductIdBuilder productIdBuilder)
        {
            // TODO: Complete member initialization
            _productRepository = productRepository;
            _productIdBuilder = productIdBuilder;
        }

Finally we’ll need to call the _productIdBuilder.BuildProductIdentifier() method to build an ID and check if the ID is null:

public void Create(ProductViewModel productViewModel)
        {
            Product product = ConvertToDomain(productViewModel);
            product.Identifier = _productIdBuilder.BuildProductIdentifier();
            if (product.Identifier == null)
            {
                throw new InvalidProductIdException();
            }
            _productRepository.Save(product);
        }

Run the tests and the new unit test should fail as BuildProductIdentifier() returned null. However, now we have another failing test: Then_repository_save_should_be_called() fails because Create throws an exception. See how useful it is to have a unit test? Let’s try and accommodate the changes.

We’ll make one breaking change: we don’t need two constructors. Remove the single-parameter constructor from ProductService. This will break two tests: Then_product_repository_should_be_called_once_per_product() and Then_repository_save_should_be_called(). As we’re not testing the return value of the IProductIdBuilder interface in those we’ll need to pass in a valid implementation that returns a non-null object. Change the Arrange section of Then_repository_save_should_be_called() to the following:

//Arrange
            var mockProductRepository = new Mock<IProductRepository>();
            mockProductRepository.Setup(p => p.Save(It.IsAny<Product>()));
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            mockIdBuilder.Setup(x => x.BuildProductIdentifier()).Returns(new ProductIdentifier());
            ProductService productService = new ProductService(mockProductRepository.Object, mockIdBuilder.Object);

The call to mockIdBuilder.Setup means that when BuildProductIdentifier() is called then please make sure that a new ProductIdentifier() object is returned.

To correct Then_product_repository_should_be_called_once_per_product() we simply need to pass in a non-null IProductIdBuilder to the ProductService to be able to compile:

var mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            ProductService productService = new ProductService(mockProductRepository.Object, mockIdBuilder.Object);

This is because the CreateMany method of the ProductService doesn’t call the BuildProductIdentifier() method. We’ll revisit the CreateMany method later in the post.

Run the tests again and they should all pass.

Let’s take another look at An_exception_should_be_thrown_if_id_is_not_created(). It passes because Moq will return the default value of the ProductIdentifier when calling BuildProductIdentifier(). The default value of an object is of course null so the test passes implicitly. However, this may not be obvious to other developers so let’s set up this expection explicitly:

Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            mockIdBuilder.Setup(i => i.BuildProductIdentifier()).Returns(() => null);

The Setup method will be familiar by now. The funny looking () => null is the lambda way of saying that the return value should be null. The test still passes but now we’re giving concise instructions about our expectations. You may be wondering where the ‘Assert’ section is. It is actually expressed by the [ExpectedException(typeof(InvalidProductIdException))] header above the method signature.

A second test worth writing is that the product should be saved if a valid non-null ID was created. Add another test method to When_creating_a_product.cs:

        [Test]
        public void The_product_should_be_saved_if_id_was_created()
        {
            //Arrange
            ProductViewModel productViewModel = new ProductViewModel() { Description = "Nice product", Name = "ProductA" };

            Mock<IProductRepository> mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            mockIdBuilder.Setup(i => i.BuildProductIdentifier()).Returns(new ProductIdentifier());
            ProductService productService = new ProductService(mockProductRepository.Object
                , mockIdBuilder.Object);

            //Act
            productService.Create(productViewModel);

            //Assert
            mockProductRepository.Verify(p => p.Save(It.IsAny<Product>()));
        }

The meaning of this test should be clear from the previous examples. We want to make sure that Save is called if ID is not null.

Out parameters

Out parameters are generally discouraged as they are a sign of a method trying to accomplish too much in its method body. However, the well-known .NET TryParse method also uses an out parameter so you may as well follow that convention and implement your own TryParse method that returns true if the value could be parsed. We’ll not create a specific method just for this purpose but you would set up the expectation on an out parameter as follows:

Mock<IManufacturerFactory> mockManufacturerFactory = new Mock<IManufacturerFactory>();
            ProductManufacturer manufacturer = new ProductManufacturer() { Address = "Sweden" };
            mockManufacturerFactory
                .Setup(m => m.TryParse(It.IsAny<string>(), out manufacturer)))
                .Returns(true);

I.e. we want to make sure that calling the TryParse method of the mock object implementing the IManufacturerFactory returns true for any string parameter.

Returning multiple values

In this section we’ll revisit the CreateMany method. After consulting the domain experts we’ve come to the conclusion that the Id of each product should be a unique integer, i.e. no two products should have the same Id. Open When_creating_multiple_products.cs and add another test method:

[Test]
        public void Then_each_product_should_receive_a_unique_id()
        {
            //Arrange
            List<ProductViewModel> productViewModels = new List<ProductViewModel>()
            {
                new ProductViewModel(){Name = "ProductA", Description="Great product"}
                , new ProductViewModel(){Name = "ProductB", Description="Bad product"}
                , new ProductViewModel(){Name = "ProductC", Description="Cheap product"}
                , new ProductViewModel(){Name = "ProductD", Description="Expensive product"}
            };
            var mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            ProductService productService = new ProductService(mockProductRepository.Object, mockIdBuilder.Object);
        }

The Arrange phase should be familiar but we’ll extend it here. We know that the ID will be of type integer so let’s define one:

Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            int productId = 1;

Next we’ll set up our expectation that the ProductIdenfier object will hold unique ID values in each iteration. Add the following after the productId initialisation.

mockIdBuilder.Setup(i => i.BuildProductIdentifier())
                .Returns(new ProductIdentifier() { RawValue = productId });

This will make sure that the ProductIdentifier will have a RawValue property of type int with a value of productId. Create the property using VS as usual. This call to Setup needs to be extended somehow as it assigns only the value of 1 nothing else whereas we need unique values in each iteration. We can achieve it as follows:

mockIdBuilder.Setup(i => i.BuildProductIdentifier())
                .Returns(new ProductIdentifier() { RawValue = productId })
                .Callback(() => new ProductIdentifier() { RawValue = productId++ })

The Callback method will make sure that productId will increase by one as we loop through the collection of Product objects. The full implementation of the test looks as follows:

        [Test]
        public void Then_each_product_should_receive_a_unique_id()
        {
            //Arrange
            List<ProductViewModel> productViewModels = new List<ProductViewModel>()
            {
                new ProductViewModel(){Name = "ProductA", Description="Great product"}
                , new ProductViewModel(){Name = "ProductB", Description="Bad product"}
                , new ProductViewModel(){Name = "ProductC", Description="Cheap product"}
                , new ProductViewModel(){Name = "ProductD", Description="Expensive product"}
            };
            var mockProductRepository = new Mock<IProductRepository>();
            Mock<IProductIdBuilder> mockIdBuilder = new Mock<IProductIdBuilder>();
            int productId = 1;
            mockIdBuilder.Setup(i => i.BuildProductIdentifier())
                .Returns(new ProductIdentifier() { RawValue = productId })
                .Callback(() => new ProductIdentifier() { RawValue = productId++ });

            ProductService productService = new ProductService(mockProductRepository.Object, mockIdBuilder.Object);
            //Act
            productService.CreateMany(productViewModels);
            //Assert
            mockProductRepository.Verify(p => p.Save(It.IsAny<Product>()), Times.AtLeastOnce());
        }

Run the tests and all 5 of them should pass. We don’t actually do anything with the Id in the CreateMany method so change the implementation to the following:

public void CreateMany(List<ProductViewModel> productViewModels)
        {
            foreach (ProductViewModel vm in productViewModels)
            {
                Product newProduct = new Product(vm.Name, vm.Description);
                newProduct.Identifier = _productIdBuilder.BuildProductIdentifier();
                _productRepository.Save(newProduct);
            }
        }

This completes our discussion on mocking return values with Moq. In the next post we’ll look into how to verify arguments passed to the system under test and how to mock exceptions.

Test Driven Development in .NET Part 5: verifying system under test with mocks using the Moq framework

Introduction

Writing unit tests can become difficult. The following scenarios will all make it more difficult to isolate the logic you’re trying to test:

  • Complex method body with a lot of branching logic
  • Code is tightly coupled to other classes
  • Code that accesses external resources, such as databases, file systems, web services etc.

In the last two cases you may even worry about how the unit tests are going to affect the external classes and resources. The good news is that these dependencies can be abstracted away and factored out with Test Doubles or Mocks. Test Doubles are objects that provide a simplified implementation of a dependency.

Example: you have a method that accepts an IDataReader object. One concrete implementation might be called FileReader that uses the standard .NET Stream classes to read a file. In the real application the code will then open a physical file, read its contents and do something with the data. While preparing a unit test you will have to send in an IDataReader object. By sending in a FileReader you may run into the following dilemmas:

  • The true logic of the method is to process the data and not to open and read a file
  • However, you cannot test the data processing logic without an IDataReader
  • If you pass in a FileReader then you must have a valid file ready on disk with valid data
  • If the test fails, then why did it fail? Is the file missing? Is the data in the file invalid? Difficult to say
  • Normally a unit test should not directly access external resources as it takes more time and unit tests should run very fast

One solution is to write a simplified implementation of IDataReader, maybe called InMemoryDataReader that doesn’t read a physical file. It instead uses a static list of in-memory data that you verified beforehand. That way you can be sure that the data that the method under test receives is perfectly valid. Also, if the unit test fails then you’ll know that it wasn’t due to the unavailability of an external file, but a failure in the processing logic.

A similar problem arises if the method under test uses external objects and calls those objects to carry out specific tasks. A unit test that fails will again be of dubious quality. Something has failed, but we’re not sure what. With mocks we can fake those dependencies.

If you don’t use any mocking framework then you will obviously need to write your mock objects by hand. If The method under test has 4 dependencies, let’s say 4 interfaces, then you’ll need to write at least 4 mock implementations in order to write a meaningful unit test. If there’s some complicated branching logic within the method then you may even have to write additional implementations of the interfaces that adhere to the different paths the code can take. The benefit of rolling your own mock objects is that you have complete control over how the mock implementations behave and that you don’t have to learn any new framework.

The downside is that you increase the unit testing code base with every new mock object. As the unit tests are also part of the code base it also needs to be maintained – a larger code base means more code to maintain. Also, the complexity of mock objects will increase with the complexity of the code under test. An even bigger problem is the fragility of such mocks. They are subject to changes in the interfaces they implement.

Mocking with the Moq framework

Before we jump into any code there’s a pattern associated with using mocks in the unit tests that you’ll need to know: Arrange-Act-Assert, aka AAA. These are three phases within the method body of a unit test.

Arrange: set up the objects necessary to write a meaningful test on the method under test, i.e. this is an initialisation phase.
Act: execute the method under test.
Assert: verify some type of outcome of running the method

Open Visual Studio 2012 – this all should work in 2010 as well – and create a blank solution. Add two class library projects to the solution: Application.Domain and Application.Tests. Remove Class1.cs from both and add reference the Domain project in the Test project. In Application.Tests add a reference to the NUnit testing framework as outlined here. You’ll also need to add the Moq framework which is a mocking library designed for .NET3.5 and above. It can be downloaded from NuGet:

Mock in NuGet

We’ll simulate a ProductService class that creates new Products through a ProductRepository. We will test the ProductService class to demonstrate AAA and the most basic usage of a mock object. We’ll use the code first approach.
Add a folder called ProductService_Tests to the Tests project. In our first test we want to verify that the ProductRepository was called from within the ProductService when its Create method was called. Add a class called When_creating_a_product.cs to the ProductService_Tests folder and then add a method called Then_repository_save_should_be_called(). Insert the necessary NUnit attributes to come to the following starting point:

[TestFixture]
    public class When_creating_a_product
    {
        [Test]
        public void Then_repository_save_should_be_called()
        {

        }
    }

So the first stage is Arrange. We follow the standard Repository pattern so we know that CustomerService will have a dependency on ICustomerRepository to carry out the actual persistence task so we’ll need to set it up. The Moq framework uses a lot of reflection to set up mocks for us and its syntax can be strange at first with its heavy use of Lambda expressions. The most important class in Moq to build mocks is called Mock – how convenient! Add the following to the test method:

//Arrange
var mockProductRepository = new Mock<IProductRepository>();

This is the way to initialise a mock object that implements the IProductRepository interface. There’s no such interface yet, but you can create it using the techniques outlined here.

We’re not done with the Arrange phase. The interface will need to have at least one method. We decide that its method will be called Save and accept a Product object which will be saved in the repository. The next important keyword of Moq is Setup. Add the following line of code to the test method:

mockProductRepository.Setup(p => p.Save(It.IsAny<Product>()));

First make sure that you create the Save method and the Product object using the built in Visual Studio tools. Setup means setting up our expectation(s) on the mock object. We expect its Save method to be called where the Save method accepts a Product object. In Moq all expectations in the Setup method will be formed using Lambda expressions. The funny looking It.IsAny just means any type of Product object.

Next we’ll create the ProductService object which depends on an IProductRepository class:

ProductService productService = new ProductService(mockProductRepository.Object);

Let VS create ProductService and its constructor. Notice the Object property of our mock object. Moq builds a concrete instance of the mocked interface object for us on the fly and the Object property will extract this implementation. We never actually see it but we don’t care either. It takes the place of the hand-made mocks we may spend a lot of time writing.

Now comes the Act phase which means invoking the actual method we want to test:

//Act
productService.Create(new ProductViewModel());

We call the Create method of the product service which accepts a ProductViewModel object. Go ahead and create those using Visual Studio. We use the View Model to communicate with the Service from the outside. This follows the strict policy of not letting the Domain objects bubble up to the projects above the Services project. Don’t worry if you haven’t come across this way of organising code, it’s not important here. Just accept that we don’t let our domain object permeate the entire solution. It’s another discussion whether this is good or bad but we’ll definitely not pursue it any further here and now.

In the Assert phase we simply say the following: ensure that everything we expected to happen really DID happen. Add the following code:

//Assert
mockProductRepository.VerifyAll();

VerifyAll comes from the Moq framework. It means that every expectation we set up in the Arrange phase should be checked.

Go ahead and run the test with Ctrl+R, A. It should fail as we didn’t provide any implementation to the auto-generated methods and classes, there are many NotImplementedExceptions out there. Recall that a first failing test is actually good. The next stage would be Green and then Refactor but for this discussion we’ll jump ahead and implement the code as follows:

IProductRepository.cs

public interface IProductRepository
    {
        void Save(Product product);
    }

Product.cs:

public class Product
    {
        public string Name { get; set; }
        public string Description { get; set; }

        public Product(string name, string description)
        {
            Name = name;
            Description = description;
        }
    }

ProductService.cs:

public class ProductService
    {
        private IProductRepository _productRepository;

        public ProductService(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        public void Create(ProductViewModel productViewModel)
        {
            Product product = ConvertToDomain(productViewModel);
            _productRepository.Save(product);
        }

        private Product ConvertToDomain(ProductViewModel productViewModel)
        {
            return new Product(productViewModel.Name, productViewModel.Description);
        }
    }

ProductViewModel.cs:

public class ProductViewModel
    {
        public string Name { get; set; }
        public string Description { get; set; }
    }

Run the test again, it should pass. We can verify that Moq is not lying to us by commenting out ‘_productRepository.Save(product);’ in ProductService.Create. Run the test with that method call commented out and you should get a failing test. The Moq Verify type of assertions will test whether the system under test behaved according to our expectations.

Increasing the complexity

The previous demo showed the absolute basics of mocking with Moq. We’ll now extend the ProductRepository to be able to insert a range of Product objects. Add a new class within ProductService_Tests called When_creating_multiple_products.cs and a method called Then_product_repository_should_be_called_once_per_product():

[TestFixture]
    public class When_creating_multiple_products
    {
        [Test]
        public void Then_product_repository_should_be_called_once_per_product()
        {

        }
    }

In the Arrange phase we’ll start by building up a list of Products that will be passed into a CreateMany method of the CustomerService class:

//Arrange
            List<ProductViewModel> productViewModels = new List<ProductViewModel>()
            {
                new ProductViewModel(){Name = "ProductA", Description="Great product"}
                , new ProductViewModel(){Name = "ProductB", Description="Bad product"}
                , new ProductViewModel(){Name = "ProductC", Description="Cheap product"}
                , new ProductViewModel(){Name = "ProductD", Description="Expensive product"}
            };

And then we’ll want to verify that the Save method of the ICustomerRepository object is executed for every ProductViewModel in the list. Add the following to the test method:

var mockProductRepository = new Mock<IProductRepository>();
            mockProductRepository.Setup(p => p.Save(It.IsAny<Product>()));
            ProductService productService = new ProductService(mockProductRepository.Object);
            //Act
            productService.CreateMany(productViewModels);
            //Assert
            mockProductRepository.VerifyAll();

Add the CreateMany method to the product service using VS. You’ll notice that the code is very similar to the one we wrote above. Run the tests and the new one should of course fail due to the unimplemented CreateMany method so let’s implement it quickly:

public void CreateMany(List<ProductViewModel> productViewModels)
        {
            foreach (ProductViewModel vm in productViewModels)
            {
                _productRepository.Save(new Product(vm.Name, vm.Description));
            }
        }

Re-run the tests and they should pass. Is this enough though? The Setup method will make sure that Save will be called at least once. However, we want it to be called for each element in the Product list i.e. exactly 4 times. Remove the call to Setup and VerifyAll, we’ll use an overload of the Verify method instead:

//Assert
            mockProductRepository.Verify(p => p.Save(It.IsAny<Product>()), Times.Exactly(productViewModels.Count));

The ‘p => p.Save(It.IsAny())’ bit will be familiar from the Setup we had before. Then we specify how many times: exactly productViewModels.Count times. It is worth checking with IntelliSense what overloads of Verify exist. Run the tests and they should succeed. To extra-double-triple-check the behaviour replace ‘productViewModels.Count’ with 2 and the test should fail.

In the next post we’ll look at how to mock return values.

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: