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.

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.

Test Driven Development in .NET Part 4: Refactoring

In this post we’ll look closer at the Refactor step of the TDD cycle. Refactoring means changing the internal implementation of a method or a class without changing the way the class can be consumed by others. In other words Refactoring shouldn’t involve changing the signatures of public methods, the name of the class, the existing constructors, i.e. anything that can be used externally. The changes you make should not break the code of the consumers of the class. These consumers include the tests as well, they should not be affected by the changes either.

The benefit of having the tests in place is that you can easily check if the functions still work as they should after refactoring.

Why refactor???

What is all this fuss about refactoring? We wrote a failing test, then made it pass, implemented the method under test so we should be done, right? Not quite. This may be true of some extremely simple methods, like adding two numbers. In real life applications if you leave your code unattended after the first refactoring cycle then eventually it will very likely grow into a monster over time due to the lack of maintenance. Unless you always write perfectly S.O.L.I.D. code all the time of course, in which case you can stop reading this post.

Think of everyday objects, such as a bicycle. You buy a bike and you may think: I can ride my bicycle every day forever after without any worries. In reality you will have to tend to your bike: oil the chain, change and pump the tires, remove the rust etc. If you don’t maintain your bike then it will decay over time. This is true of many other objects: cars, houses, computers etc., they all need regular maintenance and refinement. The code you write is also such an object. You cannot let it “rust”, you need to come back to it and ask some questions: does it perform well during stress testing? Is the method trying to achieve too much? Does it follow the Single Responsibility Principle? Can I break it down into smaller methods that each carries out one thing at a time?

The following questions are just as important: are you going to understand your code when you come back to it after a year? Is it easy to follow? Is it well documented? Is the documentation up to date?

Proper refactoring ensures that the answer to the questions is yes, or at least a lot closer to ‘yes’ than without refactoring.

You may not always have the time to refactor your code and write unit tests. Developers are often pressed by deadlines, emergency bug fixes, change requests and the like. In that case you may cut corners by forgetting about TDD altogether. Keep in mind though that you will have to repay the short term time gain in the long term with interest. The extra time you will need later comes in different forms: time spent trying to understand the code, trying to change the code, fixing the new bugs that show up due to the lack of tests.

How to refactor?

We will build on the Calculator project we started in the previous post. We’ll expand it to make it a bit more complex as it’s difficult to meaningfully refactor the extremely simple methods and classes the project currently has.

Add the following folder and files to Calculator.Domain:

Complex calculator File structure

Here comes the content of each file:

Aggregator.cs:

public class Aggregator
    {
        private readonly IList<Observation> _observations;

        public Aggregator(IList<Observation> observations)
        {
            _observations = observations;
        }

        public IEnumerable<Observation> Aggregate(IPartitioner partitioner,
                                                  ICalculator calculator)
        {
            var partitions = partitioner.Partition(_observations);
            foreach (var partition in partitions)
            {
                yield return calculator.AggregateCollection(partition);
            }
        }
    }

AveragingCalculator.cs:

public class AveragingCalculator : ICalculator
    {
        public Observation AggregateCollection(IEnumerable<Observation> observations)
        {
            return new Observation()
            {
                HighValue = observations.Average(m => m.HighValue),
                LowValue = observations.Average(m => m.LowValue)
            };
        }
    }

DefaultPartitioner.cs:

public class DefaultPartitioner : IPartitioner
    {
        private readonly int _size;

        public DefaultPartitioner(int size)
        {
            _size = size;
        }

        public IEnumerable<IEnumerable<Observation>> Partition(IList<Observation> observations)
        {
            int total = 0;
            while (total < observations.Count)
            {
                yield return observations.Skip(total).Take(_size);
                total += _size;
            }
        }
    }

ICalculator.cs:

public interface ICalculator
    {
        Observation AggregateCollection(IEnumerable<Observation> observations);
    }

IPartitioner.cs:

IEnumerable<IEnumerable<Observation>> Partition(IList<Observation> observations);

ModalCalculator.cs:

public Observation AggregateCollection(IEnumerable<Observation> observations)
        {
            double highValue = observations.GroupBy(m => m.HighValue)
                .OrderByDescending(g => g.Count())
                .Select(g => g.Key).FirstOrDefault();

            double lowValue = observations.GroupBy(m => m.LowValue)
                .OrderByDescending(g => g.Count())
                .Select(g => g.Key).FirstOrDefault();

            return new Observation()
            {
                HighValue = highValue,
                LowValue = lowValue
            };
        }

Observation.cs:

public class Observation
    {
        public double HighValue { get; set; }
        public double LowValue { get; set; }
    }

Processor.cs:

public IEnumerable<Observation> LoadData()
        {
            List<Observation> observationList = new List<Observation>();
            XDocument document = XDocument.Load("observations.xml");

            foreach (XElement element in document.Element("Observations").Elements())
            {
                double highValue = (double)element.Attribute("High");
                double lowValue = (double)element.Attribute("Low");
                Observation observation = new Observation();
                observation.HighValue = highValue;
                observation.LowValue = lowValue;
                observationList.Add(observation);
            }

            Aggregator aggregator = new Aggregator(observationList);
            IPartitioner partitioner = new DefaultPartitioner(2);
            ICalculator calculator = new AveragingCalculator();
            IEnumerable<Observation> observations = aggregator.Aggregate(partitioner, calculator);
            return observations;
        }

Add a console application to the solution called Calculator.Main and add a reference to Calculator.Domain. Program.cs will look like this:

static void Main(string[] args)
        {
            Processor processor = new Processor();
            IEnumerable<Observation> observations = processor.LoadData();
            foreach (Observation o in observations)
            {
                Console.WriteLine("{0}:{1}", o.LowValue, o.HighValue);
            }

            Console.ReadLine();
        }

Add an XML file to Calculator.Main called observations.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Observations>
  <Observation High="10" Low="3"/>
  <Observation High="11" Low="10"/>
  <Observation High="13" Low="8"/>
  <Observation High="15" Low="7"/>
  <Observation High="16" Low="5"/>
  <Observation High="11" Low="4"/>
  <Observation High="12" Low="3"/>
</Observations>

Select observations.xml in the Solution Explorer and press Alt+Enter. In the Properties window select ‘Content’ for Build Action and ‘Copy if newer’ for Copy To Output Directory.

Run the project to make sure it compiles and works. You should get the below output:

Console output of complex calculator

I will not go through the code in detail here as it is not our focus. Step through the code step by step using breakpoints and F11, it should be easy to follow.

How to refactor?

We will concentrate on Processor.cs and its LoadData() method. We pretend that we inherited this method from another developer. After all, you would not write anything like this, right? It’s only those other developers that don’t keep testability in mind who would put together such a method.

It’s an antithesis to the Single Responsibility Principle, although there are certainly a lot worse examples out there. We can identify several problems:

  • The name LoadData is not descriptive of what actually goes on in the method: it performs a lot more than just ‘load the data’
  • The method performs many things: what do we test?
  • The method introduces dependencies on external objects
  • You cannot specify the file name from the outside, you’re stuck with ‘observations.xml’
  • The method is difficult to test: which part of the method do we test? If it fails, then where does it fail exactly?

Phase 1: Cleanup refactorings

Visual Studio 2012 comes with several built-in refactoring tools that come very handy. Probably the easiest thing to do is to rename the method. Go ahead and rename the method to ‘LoadAndAggregateData’. You will see a small red rectangle appear underneath the method name:

Rename a method

Hover above the rectangle with the mouse – or press Ctrl+’-‘ while having the cursor on the method name – and you’ll see a small context menu which allows you to rename the method. This will also rename the method where it is referenced elsewhere in the code, such as in Program.cs. If you don’t do this then you have to go through the entire project and rename the references as well. You can rename parameter names, classes, namespaces etc. the same way.

A great step towards testability is to remove the inline dependency on the ‘document’ parameter. It should be injected in the method by way of method injection known from DI – Dependency Injection. It simply means that we let the method accept a parameter instead of directly building one itself. Modify the method as follows:

public IEnumerable<Observation> LoadAndAggregateData(XDocument document)
        {
            List<Observation> observationList = new List<Observation>();

            foreach (XElement element in document.Element("Observations").Elements())
            {
                double highValue = (double)element.Attribute("High");
                double lowValue = (double)element.Attribute("Low");
                Observation observation = new Observation();
                observation.HighValue = highValue;
                observation.LowValue = lowValue;
                observationList.Add(observation);
            }

            Aggregator aggregator = new Aggregator(observationList);
            IPartitioner partitioner = new DefaultPartitioner(2);
            ICalculator calculator = new AveragingCalculator();
            IEnumerable<Observation> observations = aggregator.Aggregate(partitioner, calculator);
            return observations;
        }

Now we can pass in any type of XML document, the method doesn’t need to get it from a file. This is a breaking change but has a very positive effect so we’ll keep it. The clients will need to adjust like in our case in Program.cs:

IEnumerable<Observation> observations = processor.LoadAndAggregateData(XDocument.Load("observations.xml"));

The code that reads the XML should go into a separate method so we’ll factor it out. Highlight all rows from ‘List observationList’ to the closing bracket of the foreach loop. Right-click the selection and then select Refactor, Extract Method…:

Extract method menu point

In the Extract Method window set the method name to ParseMeasurements and click OK. You should see that the highlighted code was factored out to a separate private method. You can remove the ‘static’ keyword from the method signature. The variable observationList is now built using the ParseMeasurements method.

We’ll do the same thing to the measurement aggregation bit. Highlight the rows from ‘Aggregator aggregator’ to the return statement. Extract a new method called AggregateMeasurements using the technique described above and you should come to the following code:

public IEnumerable<Observation> LoadAndAggregateData(XDocument document)
        {
            List<Observation> observationList = ParseMeasurements(document);
            return AggregateMeasurements(observationList);
        }

        private IEnumerable<Observation> AggregateMeasurements(List<Observation> observationList)
        {
            Aggregator aggregator = new Aggregator(observationList);
            IPartitioner partitioner = new DefaultPartitioner(2);
            ICalculator calculator = new AveragingCalculator();
            IEnumerable<Observation> observations = aggregator.Aggregate(partitioner, calculator);
            return observations;
        }

        private List<Observation> ParseMeasurements(XDocument document)
        {
            List<Observation> observationList = new List<Observation>();

            foreach (XElement element in document.Element("Observations").Elements())
            {
                double highValue = (double)element.Attribute("High");
                double lowValue = (double)element.Attribute("Low");
                Observation observation = new Observation();
                observation.HighValue = highValue;
                observation.LowValue = lowValue;
                observationList.Add(observation);
            }
            return observationList;
        }

The last immediate change we’ll introduce has to do with the value 2 in the DefaultPartitioner constructor. This value can be confusing to those who read your code. Why 2? What’s 2? What does it mean? It’s more meaningful to introduce constants. Add the following constant to the class:

private const int groupSize = 2;

…and replace ‘2’ with the ‘groupSize’ constant.

Phase 2: factoring out abstractions

The above changes were a great relief: they have brought with them a higher degree of maintainability and readability. You may well be aware of abstractions – polymorphism – in an object oriented programming language: abstract classes and interfaces. They are useful in many ways: they introduce loose coupling between classes, increase testability as you can pass in any implementation to the method under test, they help factor out common attributes of related classes and they also increase the extensibility of your classes as many different implementations can be added to the class.

Let’s see what can do to improve the Processor class. We’ll first extract an interface from the Processor implementation. This will allow us to introduce different types of Processors in the future, ones that perhaps carry out the data aggregation in a different way. It will also enable us to pass in any IProcessor object into a method under test that is expecting an IProcessor parameter in its method signature. Then the unit test will not be tied to a single implementation.

Place the cursor on ‘Processor’, right-click it, select Refactor and Extract Interface… The Extract Interface window will provide reasonable defaults so just press OK. You’ll see a new file called IProcessor.cs in the solution. Locate it and modify it slightly to include some using statements instead of the long fully qualified class definitions:

using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Calculator.Domain.Complex
{
    public interface IProcessor
    {
        IEnumerable<Observation> LoadAndAggregateData(XDocument document);
    }
}

You’ll also see that Processor now implements IProcessor:

public class Processor : IProcessor

We’ll also introduce a base class for the Processor so that all derived classes must follow the AggregateMeasurements + ParseMeasurements setup. Add a class called ProcessorBase to the Complex folder of Calculator.Domain:

public abstract class ProcessorBase
    {
        public abstract IEnumerable<Observation> AggregateMeasurements(List<Observation> observationList);
        public abstract List<Observation> ParseMeasurements(XDocument document);
    }

Make Processor derive from ProcessorBase:

public class Processor : ProcessorBase, IProcessor

…and change the signatures of the implemented methods to the following:

public override IEnumerable<Observation> AggregateMeasurements(List<Observation> observationList)
public override List<Observation> ParseMeasurements(XDocument document)

We could continue refactoring but we’ll stop here. The purpose of the post was to show you the importance of refactoring.

In the next post we’ll start looking at a special topic within TDD: mocking. Mocking is important in order to build dependencies for the system under test. The framework we’ll use is called Moq.

Test Driven Development in .NET Part 3: Test fixtures, categories, the sad path

This post will continue our discussion on TDD in .NET with NUnit. Here we’ll look at several smaller topics before moving onto larger chunks to avoid one big chatty post. In particular we’ll be looking at the following:

  • Using TestFixture to run multiple tests
  • Test categories
  • Testing for ‘bad’ input: the Sad Path
  • Specialised assertions

Have many tests at once

As your test suite grows you may run into a lot of repetitive code. If you’d like to test a method with a lot of different values then one solution is to copy and paste the first test and just replace the input parameters – goes clearly against the Don’t Repeat Yourself principle.

To demonstrate how you can pass in several different parameters to the system under test we’ll start a new project.

Open Visual Studio and create a Blank Solution with a name you like. Add a Class Library to the solution named Calculator.Domain. Add another Class Library called Calculator.Tests. Remove the Class1.cs files from each project. Add a folder called Calculator_Tests to the .Tests project. Add a class called When_adding_two_integers.cs. Add a reference to NUnit as described in this blog post. Decorate the class with the TestFixture attribute:

[TestFixture]
    public class When_adding_two_integers
    {
    }

Add the following Test to the class:

[Test]
        public void Then_sum_is_correct()
        {
            SimpleCalculator simpleCalculator = new SimpleCalculator();
            CalculationResult calculationResult = simpleCalculator.Add(4, 7);
            Assert.AreEqual(11, calculationResult.Outcome);
        }

The code will of course not compile as we don’t have these classes and properties ready yet. Using the techniques we saw previously create them in the Calculator.Domain project. Run the test (Ctrl +R, A) and you should get a failing test as the Add method is not yet implemented. Recall, this is the first phase – Red.

Locate the CalculationResult class that was created and change the type of the Outcome property to int:

public class CalculationResult
    {
        public int Outcome { get; set; }
    }

Next go to SimpleCalculator.cs and implement the Add method:

public CalculationResult Add(int inputOne, int inputTwo)
        {
            return new CalculationResult() { Outcome = inputOne + inputTwo };
        }

Run the test again and you should get a passing test.

Testing the Add method with only two different parameters may not be enough. You want to test it with small numbers, large numbers, negative numbers etc. One naive way would be to add a second test:

[Test]
        public void Then_sum_is_still_correct()
        {
            SimpleCalculator simpleCalculator = new SimpleCalculator();
            CalculationResult calculationResult = simpleCalculator.Add(1, 2);
            Assert.AreEqual(3, calculationResult.Outcome);
        }

First we’ll factor out the SimpleCalculator initialisation:

[TestFixture]
    public class When_adding_two_integers
    {
        private SimpleCalculator _simpleCalculator;

        [SetUp]
        public void AssignVariables()
        {
            _simpleCalculator = new SimpleCalculator();
        }

        [Test]
        public void Then_sum_is_correct()
        {
            CalculationResult calculationResult = _simpleCalculator.Add(4, 7);
            Assert.AreEqual(11, calculationResult.Outcome);
        }

        [Test]
        public void Then_sum_is_still_correct()
        {
            CalculationResult calculationResult = _simpleCalculator.Add(1, 2);
            Assert.AreEqual(3, calculationResult.Outcome);
        }
    }

The next step is to make sure that _simpleCalculator.Add can be called with many different values without copy-pasting the Test methods over and over again. The TextFixture attribute has an overloaded constructor which allows this, but first we’ll need to prepare a couple of things. Add the following private fields to the class:

private int _firstParameter;
        private int _secondParameter;
        private int _result;

Also, add the following constructor:

public When_adding_two_integers(int firstParameter, int secondParameter, int result)
        {
            _firstParameter = firstParameter;
            _secondParameter = secondParameter;
            _result = result;
        }

Remove the Then_sum_is_still_correct() test method. Change the Then_sum_is_correct() method to the following:

[Test]
        public void Then_sum_is_correct()
        {
            CalculationResult calculationResult = _simpleCalculator.Add(_firstParameter, _secondParameter);
            Assert.AreEqual(_result, calculationResult.Outcome);
        }

The TextFixture attribute allows us to pass in parameters to the constructor. Add the following attributes above the class declaration:

[TestFixture(1,1,2)]
    [TestFixture(2, 2, 5)]
    [TestFixture(3, 2, 2)]
    [TestFixture(4, 4, 8)]
    [TestFixture(5, 6, 11)]
    [TestFixture(12, 10, 21)]
    [TestFixture(13, 14, 27)]
    [TestFixture(0, 0, 0)]

Yes, all of them. Look at the signature of the test class constructor: it requires three integers. You’ll see that we’re passing in three integers in the TextFixture object: the firstParamater, the secondParameter and the result values. The values are assigned to the local _firstParameter, _secondParameter and _result fields and their values are used in the Then_sum_is_correct() method. So the first attribute [TestFixture(1,1,2)] will be translated to ‘add 1 and 1 and assert that the result is 2’ in the Then_sum_is_correct() method. All TestFixture rows will be run by the test runner. Note that we’ve deliberately introduced a couple of errors, such as the second one [TestFixture(2, 2, 5)]. Run the tests now and you should see 3 failing and 5 passing tests:

Test fixture with many tests

Correct the values in the TestFixture constructor as necessary to get 8 passing tests. So, we’ve got 8 tests for the price of one, that sounds like a good deal.

Category

For organisational purposes you can group the tests using the Category attribute which accepts a string parameter. Add the following attribute above the first TestFixture attribute:

[Category("Calculator.Domain")]

Run the tests again and you’ll see no change. Go to the Group By icon in the Test Explorer and select Traits:

Group By category in Test Explorer

You’ll then see that the tests are organised according to their category:

Tests grouped by category

This is useful when you have many more test fixtures which can be grouped. This adds another level in the test hierarchy.

The sad path

So far we’ve tested very simple values where we subconsciously assumed that the user will provide ‘good’ inputs, i.e. inputs that the Add method can handle. This is called the Happy Path. However, what if one of the parameters is int.Max? Adding something to int.Max will give unexpected results.

It is important to keep in mind that we should also test inputs that our code should not deal with. Add a subfolder called ‘SadPath’ within the ‘Calculator_Tests’ folder. Add a class called When_adding_integer_to_maximum.

Start with the following skeleton:

[Category("Calculator.Domain")]
    [TestFixture]
    public class When_adding_integer_to_maximum
    {
        private SimpleCalculator _simpleCalculator;

        [SetUp]
        public void AssignVariables()
        {
            _simpleCalculator = new SimpleCalculator();
        }

        [Test]
        public void Method_should_throw_not_supported_exception()
        {

        }
    }

The method name describes what we would like to see: the Add method should throw a NotSupportedException when passing in at least one int.Max value instead of returning a dubious result.

We’ll use another attribute called ExpectedException. As the name implies it decorates tests where we expect the tested method to throw an exception. So the test passes if the exception is thrown and fails otherwise. Update the Method_should_throw_not_supported_exception() test to the following:

[Test]
        [ExpectedException(typeof(NotSupportedException))]
        public void Method_should_throw_not_supported_exception()
        {
            _simpleCalculator.Add(int.MaxValue, 3);
        }

In other words the Add method is expected to throw a NotSupportedException otherwise the test fails. Run the test… …and this particular test will fail as it did not throw the exception:

Expected exception not thrown

Remember: according to the Red-Green-Refactor cycle this is a good sign.

Go to the body of the Add method and update it as follows:

public CalculationResult Add(int inputOne, int inputTwo)
        {
            if (inputOne == int.MaxValue || inputTwo == int.MaxValue)
            {
                throw new NotSupportedException("Maximum values not supported.");
            }
            return new CalculationResult() { Outcome = inputOne + inputTwo };
        }

Re-run the tests and you’ll see that the test passes.

Specialised assertions

It’s worthwhile to simply type ‘Assert.’ in Visual Studio and check the available choices. You’ll find lots of interesting methods, such as IsNull, IsNotNull, LessOrEqual, Greater etc. However, there are some specialised cases that you won’t find in here but have to look elsewhere:

  • StringAssert
  • CollectionAssert

It’s easy to guess what these are for: strings and collections. If you wish to make sure that a string parameter fulfils some condition then StringAssert has methods such as DoesNotEndWith or DoesNotContain.

In case a Collection type of object, such as a List needs to be inspected then CollectionAssert has methods such as IsSubsetOf or IsEmpty.

Thus there is a wide range of cases you can write tests for.

This was a rather short entry on a couple of smaller topics in TDD that didn’t really fit in a larger post. In the next post we’ll continue looking at the Refactor phase.

Test Driven Development in .NET Part 2: continuing with Red, Green, Refactor

In the previous post we looked at the very basics of test first development in .NET and more specifically the Red-Green-Refactor cycle. This post is a direct continuation so we’ll build on the test project we started working on.

Pass the test

Currently we have a failing test in our test project: the SharesTest() fails. Remove the ‘throw new NotImplementedException’ from the Partition method and replace it with the simplest possible return statement that will make the compiler happy:

return new Partition();

Run the tests now and we should still have a failing test: the Size property was initialised to 0 which is different from the expected value of one:

Shares test still fails

It’s now time to make sure that our test passes. The simplest way is probably the following:

public Partition Partition(List<Share> sharesList)
        {
            return new Partition() { Size = sharesList.Count };
        }

Run the test now and you should see that SharesTest indeed passes:

Shares test passed

We assign the Count property of the sharesList parameter to the Size property of the Partition object. As we passed in a list with a single share then the result will be 1 which is the expected result. This is of course not a real life implementation yet. The Partition method doesn’t even look at the integer in the Partitioner constructor. That’s OK as we’ll now move on to the next step in the cycle: Refactoring.

The code generator called the integer parameter of the Partition constructor ‘p’. That’s not very descriptive so change the code as follows:

        private int _partitionSize;

        public Partitioner(int partitionSize)
        {
            this._partitionSize = partitionSize;
        }

Re-run the test to make sure it’s working. This is a good exercise: you change something in the implementation and then run the tests to check whether you broke something.

We now know a bit more about the purpose of SharesTest: it tests whether a group of size one is partitioned into a Partition of size one. There are different ways to name a test but a descriptive approach can be worthwhile. Rename the SharesTest method to Partitioning_a_list_of_one_item_by_one_produces_a_partition_of_size_one().

Run the test and you’ll see the new method name appear in the Test Explorer. As the name describes what the test does it’s easy to see which functions pass or fail. SharesTest doesn’t tell you anything: what Shares? What functionality? It passes, but what is it that passes? Choosing a long name like that saves you a lot of time: the title tells you which functionality is broken.

We can again stop for some reflection: is it enough to test a single case? Should we check other partition values such as -1, 0, 2, 100 etc.? Testing the value of 1 is probably not enough as the users may pass in values that are outside of your control.

You may be tempted to add several assertions into one test but resist that: you should only have a single assertion within one test. We should always have one single assertion per unit test. We test one scenario and not more. Then if the test fails then you’ll immediately see which functionality is failing.

Insert a new test in FinanceTests, a test that checks if a collection of 2 items returns a Partition of size 2:

        [Test]
        public void Partitioning_a_list_of_two_items_by_one_produces_a_partition_of_size_two()
        {
            List<Share> sharesList = new List<Share>();
            Share shareOne = new Share();
            shareOne.Maximum = 100;
            shareOne.Minimum = 13;
            sharesList.Add(shareOne);
            sharesList.Add(new Share() { Maximum = 50, Minimum = 10 });            

            Partitioner partitioner = new Partitioner(1);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(2, partition.Size);
        }

We now have a collection of 2 shares. The collection is partitioned into groups of one and we expect the resulting Partition two have two elements. Run the tests and you’ll see that it passes. It’s obvious: our implementation of the Partition method still doesn’t even look at the _partitionSize property so it doesn’t make any difference whether we pass in a collection of 2, 5 or 100. So it’s now time to come up with something more realistic.

Add another property to the Partition object:

public IList<IList<Share>> PartitioningResult;

The result of the partitioning process should be a list of lists shares. If we start with a list of 10 shares which should be cut into two subgroups of 5 then we’ll end up with a list of lists where the individual subgroups have a size of 5. The Partition method might look like this:

public Partition Partition(List<Share> sharesList)
        {
            IList<IList<Share>> partitioningResult = new List<IList<Share>>();
            int total = 0;
            while (total < sharesList.Count)
            {
                List<Share> subGroup = sharesList.Skip(total).Take(_partitionSize).ToList();
                partitioningResult.Add(subGroup);
                total += _partitionSize;
            }

            return new Partition() { PartitioningResult = partitioningResult, Size = partitioningResult.Count };
        }

Inspect the code and make sure you understand what it is doing. It is straightforward: it chops up the incoming sharesList parameter into subgroups using LINQ and assigns the subgroups to the Partition object along with a new definition of Size. Run the tests and you’ll see that it passes.

The next phase would be to decide what scenarios to test: what if we have a list of 5 shares and want to partition them into groups of two. Should the Partition function throw an exception? Should it return lists of 2-2-1? Or should it drop the element(s) that don’t fit the partition size? These are all questions that the domain expert should be able to answer so that you can write proper tests.

You can see now that a well written test suite will function as a list of specifications. You can of course have the specs listed in a Word document, but honestly, who has the time and energy to read and maintain that? How can you test the specifications in a Word document? If you instead write the tests directly in the Visual Studio editor those will never expire and with meaningful test method names will tell you clearly how the software is supposed to behave.

Test code quality

Test code is also an integral part of the solution so it should also be maintainable. You may think that the test project is less important than production code. The truth is that all important design rules, such as DRY (Don’t Repeat Yourself) still apply here. It needs to be well organised and documented so that you can find your way around when you come back to it to make changes.

As you add more and more test cases in our Finance test project you may be tempted to copy and paste the original Partitioning_a_list_of_one_item_by_one_produces_a_partition_of_size_one method, rename it and replace the parameters that are required Partitioner, Partition and Assert. Why would you copy and paste any bit of code? To save time: it boring to type out the List of shares variable that’s needed in every assertion.

It’s a better idea to go with a helper method:

private List<Share> CreateSharesListOfSize(int size)
        {
            List<Share> shares = new List<Share>();
            for (int i = 0; i < size; i++)
            {
                shares.Add(new Share(){Maximum = 130, Minimum = 15};
            }
            return shares;
        }

The refactored test methods will look like this:

        [Test]
        public void Partitioning_a_list_of_one_item_by_one_produces_a_partition_of_size_one()
        {
            List<Share> sharesList = CreateSharesListOfSize(1);
            Partitioner partitioner = new Partitioner(1);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(1, partition.Size);
        }

        [Test]
        public void Partitioning_a_list_of_two_items_by_one_produces_a_partition_of_size_two()
        {
            List<Share> sharesList = CreateSharesListOfSize(2);           

            Partitioner partitioner = new Partitioner(1);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(2, partition.Size);
        }

Additional considerations of tests

Besides being maintainable tests should be:

  • Repeatable
  • Independent
  • Test only public members
  • Atomic
  • Deterministic
  • Fast

A repeatable test means that if a test fails then it should always fail. We can’t say that a test fails between 10am and 5pm, otherwise there’s some external Date function that the test has no control of. Make sure that all those dependencies are controlled by the test method to avoid any such constraints.

Independent tests are tests that can be run in any order without affecting the pass/fail result. There should be no specification saying that test A must be run before test B for it to give the correct result. Don’t make a test dependent on the state left over by another test. Every test should have all necessary dependencies at their disposal and should start with a clean slate.

Testing public members only puts us in the shoes of the client, i.e. the consumer of the API. While writing the initial tests you are forced to think through the design of the API: what objects and methods are needed, what should we call them, what parameters should they take etc. A client is ultimately interested in the public design of the API not in the private elements which they do not even have visibility of. In addition, by testing public members only we can concentrate on the business rules and leave unimportant internal implementation details alone. An unimportant implementation detail is e.g. the assignment of the private variable in the Partitioner constructor. Do we really need to test if the Partitioner’s private integer field was assigned the value of the incoming parameter? Not really, it’s so trivial and it’s an internal implementation detail.

Atomic means that a unit test tests only one thing at a time, meaning you will have only one Assert statement within the body of the unit test.

A deterministic unit test is one that always provides one affirmative outcome: either pass or fail with 100% certainty, “maybe” and “almost” are not good enough.

You can guess what “fast” means. However, it’s not enough to say “yeah, it’s quite fast”. A good unit test runs VERY fast, we’re talking about 10-50 milliseconds. You should eliminate all factors that slow down the execution of the unit test. Accessing external resources such as web services, databases, physical files make unit test execution slower – and also less reliable as those resources must always be up and running and be in a state that is required by the code under test. We will look at such scenarios on later posts dealing with mocking dependencies.

How to organise the tests

There are certainly many ways to organise a test project. 10 developers may give you 11 different answers, but the following can work for many out there:

  • Make sure to include your tests in a separate .NET project
  • You should have as many test projects as you have ‘normal’ projects. Example: if your solution consists of Application.Web and Application.Domains then you should have two corresponding .NET test projects: Application.Web.Tests and Application.Domains.Tests
  • One level down is the namespace, e.g. Finance. For every namespace you should have a Namespace_Test folder in the correct .NET test projects, Finance_Test in this example
  • Below the namespace we have the Class, e.g. Share. For each class you should have a Class_Test folder, Share_Test in this example
  • Within the Share_Test folder we’ll have our test class which tests the behaviour of the Share object
  • Behaviour means the core business logic and making sure that unimportant internal implementation details are not tested. Those tests are not worth writing. E.g. testing a getter and setter is futile unless they incorporate important business logic, such as refusing certain values

So our little .NET solution might look like this after some renaming:

Proposed test class organisation

You may be asking why the test suite of the Partitioner class has such a strange name, When_partitioning_shares.cs. Besides the fact that it is what we test, i.e. partition a list of shares, check how the test class name and the individual test cases can be read in the Test explorer:

Naming the test class

When partitioning shares, partitioning a list of two items by one produces a partition of size two. This sentence gives you the scenario and the expected outcome.

Keep test code DRY

The DRY, i.e. don’t repeat yourself principle applies to the test code as well. There will be parts in the code that all the test methods will need. In our example a list of shares is created in Partitioning_a_list_of_one_item_by_one_produces_a_partition_of_size_one() and Partitioning_a_list_of_two_items_by_one_produces_a_partition_of_size_two(). Remove these two methods and instead add the following two:

[Test]
        public void Partitioning_a_list_of_four_items_by_one_produces_a_partition_of_size_four()
        {
            List<Share> sharesList = CreateSharesListOfSize(4);

            Partitioner partitioner = new Partitioner(1);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(4, partition.Size);
        }

        [Test]
        public void Partitioning_a_list_of_four_items_by_four_produces_a_partition_of_size_one()
        {
            List<Share> sharesList = CreateSharesListOfSize(4);

            Partitioner partitioner = new Partitioner(4);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(1, partition.Size);
        }

        [Test]
        public void Partitioning_a_list_of_four_items_by_two_produces_a_partition_of_size_two()
        {
            List<Share> sharesList = CreateSharesListOfSize(4);

            Partitioner partitioner = new Partitioner(2);
            Partition partition = partitioner.Partition(sharesList);

            Assert.AreEqual(2, partition.Size);
        }

i.e. we run two tests on a list of 4 shares in all 3 cases. The code that builds the the list is repeated in every test method. As it turns out NUnit – and in fact all major test frameworks out there – makes it easy to run a piece of code before every test method is run in the test suite. This “pre-test” code must be decorated with the [SetUp] attribute. Update the test suite to the following:

[TestFixture]
    public class When_partitioning_shares
    {
        List<Share> _sharesList;

        [SetUp]
        public void SetupTest()
        {
            _sharesList = CreateSharesListOfSize(4);
        }

        [Test]
        public void Partitioning_a_list_of_four_items_by_one_produces_a_partition_of_size_four()
        {
            Partitioner partitioner = new Partitioner(1);
            Partition partition = partitioner.Partition(_sharesList);

            Assert.AreEqual(4, partition.Size);
        }

        [Test]
        public void Partitioning_a_list_of_four_items_by_four_produces_a_partition_of_size_one()
        {
            Partitioner partitioner = new Partitioner(4);
            Partition partition = partitioner.Partition(_sharesList);

            Assert.AreEqual(1, partition.Size);
        }

        [Test]
        public void Partitioning_a_list_of_four_items_by_two_produces_a_partition_of_size_two()
        {
            Partitioner partitioner = new Partitioner(2);
            Partition partition = partitioner.Partition(_sharesList);

            Assert.AreEqual(2, partition.Size);
        }

        private List<Share> CreateSharesListOfSize(int size)
        {
            List<Share> shares = new List<Share>();
            for (int i = 0; i < size; i++)
            {
                shares.Add(new Share(){Maximum = 130, Minimum = 15});
            }
            return shares;
        }
    }

The SetupTest method will be run before every other test method in the file. It simply assigns a value of four shares to the private _sharesList variable.

Conversely if you decorate your method with the TearDown attribute it will be run AFTER each test method execution. The TearDown method can be used to reset some state to an initial value or clean up resources.

It’s quite tedious to create all these test cases, right? It would be best to create one test method and somehow run the same method using many different input parameters without having to copy-paste the existing code. It is possible using the TestFixture attribute. How it is done will be the topic of the next post – amongst several other features.

Test Driven Development in .NET Part 1: the absolute basics of Red, Green, Refactor

In this series of posts we’ll look at ways of introducing Test Driven Development in a .NET project. I’ll assume that you know the benefits of TDD in general and rather wish to proceed with possible implementations in .NET.

The test project

Open Visual Studio 2012 and create a Blank Solution. Right click the solution and select Add… New Project. Add a new C# class library called Application.Domain. You can safely remove the automatically inserted Class1.cs file. You should have a starting point similar to the following:

TDD project starting point Visual Studio

This Domain project represents the business logic we want to test.

Add another C# class library to the application and call it Application.Domain.Tests. Delete Class1.cs. As we want to test the domain logic we need to add a reference to the Application.Domain project to the Tests project.

Also, we’ll need to include a testing framework in our solution. Our framework of choice is the very popular NUnit. Right-click References in Application.Domain.Tests and select Manage NuGet Packages. Search for ‘nunit’ and then install two following two packages:

NUnit projects in NuGet

The NUnit.Runner will be our test runner, i.e. the programme that runs the tests in the Tests project.

You should end up with the below structure in Visual Studio:

VS solution with NUnit installed

We are now ready to add the first test to our project.

A test is nothing else but a normal C# class with some specific attributes. These attributes declare that a class is used for testing or that a method is a test method that needs to run when we test our logic. Every testing framework will have these attributes and they can be very different but serve the same purpose. In NUnit a test class is declared with the TextFixture attribute and a test method is decorated with the Test attribute. These attributes help the test runner identify where to look for tests. It won’t just run random methods, we need to tell it where to look.

This means that it is perfectly acceptable to have e.g. helper methods within the Tests project. The test runner will not run a method that is not decorated with the Test attribute. You can have as many test methods within a Test project as you wish.

The test framework will also have a special set of keywords dedicated to assertions. After all we want our test methods to tell us whether the test has passed or not. Example: we expect our calculator to return 2 when testing for ‘1+1’ and we can instruct the test method to assert that this is the case. This assertion will then pass or fail and we’ll see the result in the test runner window.

Add a new class to Tests called DomainTestFixture and decorate it with the TestFixture attribute:

[TestFixture]
    public class DomainTestFixture
    {
    }

You will be asked to add a using statement to reference the NUnit.Framework namespace.

A test method is one which doesn’t take any parameters and doesn’t return any values. Add the first test to the test class:

[TestFixture]
    public class DomainTestFixture
    {
        [Test]
        public void FirstTest()
        {

        }
    }

To introduce an assertion use the Assert object. Type ‘Assert’ within FirstTest followed by a period. IntelliSense will show a whole range of possible assertions: AreEqual, AreNotEqual, Greater, GreaterOrEqual etc. Inspect the available assertions using IntelliSense as you wish. Let’s test a simple math problem as follows:

[Test]
        public void FirstTest()
        {
            int result = 10 - 5;
            Assert.AreEqual(4, result);
        }

…where ‘4’ is the expected value of the operation and ‘result’ is the result by some operation. Imagine that ‘result’ comes from a Calculator application and we want to test its subtraction function by passing in 10 and 5. Let’s say that we make a mistake and expect 10 – 5 to be 4. This test should obviously fail.

In order to run the test in the NUnit test runner go to Tools, Extensions and Updates. Click ‘Online’ and the search for NUnit. Install the following package:

NUnit test adapter in Visual Studio

You’ll need to restart Visual Studio for the changes to take effect. Then go to Test, Run, All Tests (Ctrl R, A) which will compile the project and run the NUnit tests. You will receive the outcome in the Test Explorer window:

NUnit test explorer first test

As expected, our test failed miserably. You’ll see that the expected value was 4 but the actual outcome was 5. You’ll also receive some metadata: where the test occurred – FirstTest -, the source – DomainTestFixture.cs and the stacktrace.

Go back and fix the assertion:

Assert.AreEqual(5, result);

Select Run All in the Test Explorer and you’ll see that the red turned green and our test has passed. We can move on to a more realistic scenario and we will follow a test-first approach: we’ll write a test for a bit of code that does not even exist yet. The code to be tested will be generated while writing the test.

Let’s add a new class in Tests called FinanceTests.cs. We’ll pretend that we’re working on a financial application that administers shares. It happens often that you’re not sure what to call your test classes and test methods but don’t worry about them too much. Those are only names that can be changed very easily. Let’s add our first Test:

[TestFixture]
    public class FinanceTests
    {
        [Test]
        public void SharesTest()
        {

        }
    }

You’ll see that SharesTest sounds extremely general but remember: in the beginning we may not even know exactly what our Domain looks like. We’ll now test the behaviour of a collection of shares. Add the following bit of code to SharesTest:

List<Share> sharesList = new List<Share>();

This won’t compile obviously at first but we can use Visual Studio to create the object for us. Place the cursor on ‘Share’ and press Ctrl +’.’. You’ll see that a small menu pops up underneath ‘Share’. You can select between Generate class and Generate new type. Select Generate new type. Inspect the possible values in each drop-down menu in the Generate New Type window, they should be self-explanatory. Select the following values and press OK:

Generate new type in VS

You’ll see that a file called Share.cs was created in the Domain project. Next add the following to SharesList:

Share shareOne = new Share();
shareOne.Maximum = 100;
shareOne.Minimum = 13;
sharesList.Add(shareOne);

Again, the code won’t compile first. You can follow the same procedure as with the Share class: place the cursor on ‘Maximum’ and press Ctrl + ‘.’. Select ‘Generate property stub’. Go to Share.cs and you’ll see that an Integer property called Maximum has been added. Do the same with ‘Minimum’. At this point your Share class should look like this:

public class Share
    {
        public int Maximum { get; set; }
        public int Minimum { get; set; }
    }

You’ll notice that at this point we only added a single Share to our shares list. That’s OK, we’ll start with the simplest possible case. This is always a good idea in TDD: always start with the simplest case which is easy to test and easy to write an assertion for. Example: if you want to test a Calculator you probably won’t start with e + Pi as the first test case but something simpler such as 2 + 3. When your test is complete for the simple cases then you can move on to the more difficult ones.

Next we would like to do something with this Shares collection. Let’s imagine that we’re writing code to group the elements in the collection in some way. So we may write the following code in SharesTest():

Partitioner partitioner = new Partitioner(1);
            var partition = partitioner.Partition(sharesList);

This is the time to reflect: what name should we give to the class that will group the list elements? What should the method be called? What type of value should it return? I’m a not great fan of the ‘var’ keyword but in this case it comes in handy as I’m not sure what type of object the Partition method should return. The integer we pass in the Partitioner constructor means that we want to group elements by one. Again, we should stop and reflect: does it make sense to allow users to group items by one? Can they pass in 0 or negative values? Or even int.Max? Should we throw an exception then? These are all rules that you will need to consider, possibly with the product owner or the domain expert.

If we allow users to group the items by one then we should probably test for it. Add the following assertion:

Assert.AreEqual(1, partition.Size);

…meaning that if we instruct the Partitioner to create groups of one then the size of the resulting partition should be 1. Now I have also decided that the Partition() method should return a… …Partition! Update the relevant line as follows:

Partition partition = partitioner.Partition(sharesList);

Using the technique we used before create the Partitioner and Partition classes, the Partition method stub and the Size property stub. Don’t worry about the implementations yet. Make sure that you select the Domain project when creating the classes. The Partitioner class should look as follows:

public class Partitioner
    {
        private int p;

        public Partitioner(int p)
        {
            // TODO: Complete member initialization
            this.p = p;
        }

        public Partition Partition(List<Share> sharesList)
        {
            throw new NotImplementedException();
        }
    }

Partition.cs:

public class Partition
    {
        public object Size { get; set; }
    }

Overwrite the type of the Size property to ‘int’.

At this point the projects should compile just fine. Run the test by pressing Ctrl R, A and see what happens. You will of course see that our SharesTest has failed:

First shares test failure in visual studio

We have not implemented the Partition method yet, so we obviously cannot have a passing test.

This is exactly the first thing that we wanted to happen: a failing test.

The Red – Green – Refactor cycle

The Red – Green – Refactor cycle is a fundamental one in TDD. We’re at the Red stage at present as we have a failing test which correspond to Step 1: Create a failing test. You may wonder why this is necessary: a failing test makes sure that our method under test is testable. It is important to see that it can fail. If a method never ever can fail then it is not testable. Therefore make sure that you follow this first step in your test creation. The first step involves other important things we have to consider: name of the classes, name of methods, parameter types, return types, business rules etc. These are all very important considerations that you need to take into during this first step.

Step 2, i.e. Green involves a minimalistic implementation of our method stub(s): write just enough to make the test pass, i.e. replace the red light with green. Do not write the complete implementation of the method just yet, that will happen in different stages.

Step 3 is Refactoring, which is the gradual implementation of the method under test. This is a gradual process where you extend the implementation of the method without changing its external behaviour, i.e. the signature, and run the test over and over again to make sure that the method still fulfills the assertion. Did the change break the tests? Or do the tests still pass? You can come back to your code a year later and still have the tests in place. They will tell you immediately if you’ve broken something.

You may think that all this is only some kind of funny game to produce extremely simple code. We all know that real life code is a lot more complicated: ask a database, run a file search, contact a web service etc. How can those be tested? Is TDD only meant for the easy stuff in memory? No, TDD can be used to test virtually anything – as long as the code is testable. If you follow test first development then testability is more or less guaranteed. There are ways to remove those external dependencies such as Services, Repositories, web service calls etc. and test the REAL purpose of the method. The real purpose of a method is rarely just to open a file – it probably needs to read some data and analyse it.

If, however, you write lengthy implementations at first and then write the tests then testability is at risk. It’s easy to fall into traps that make testability difficult: dependencies, multiple tasks within a method – violating the Single Responsibility Principle, side effects etc. can all inadvertently creep in.

We’ll stop here at the Red phase of the TDD cycle – the next post will look the Green and Refactor.

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.