Kash Farooq's software development blog

.NET Developer

Posts Tagged ‘Test Driven Development’

Using Moq callbacks to check complex arguments sent to a dependency

Posted by Kash Farooq on June 16, 2013

I’ve written before about the various ways you can test the contents of a complex parameter sent to a dependency. The messages you see in RhinoMocks and Moq when a test fails aren’t always clear.

You can use Moq callbacks to give clear test failure messages.

Consider the system under test. Your creating an order, and using some of the data in the order object to create a customer. Obviously, you would have written this code test-driven – the aim of the test would be to ensure the customer object is created properly.

public class OrderService
{
  private readonly ICustomerService _customerService;

  public OrderService(ICustomerService customerService)
  {
    _customerService = customerService;
  }

  public void CreateOrder(Order order, int createdBy)
  {
     var customer = new Customer
        {
           FirstName = order.FirstName,
           LastName = order.FirstName //intentional bug
        };
    _customerService.Save(customer, createdBy);

    //TODO: do some other stuff with the order.
  }
}

In a test, let’s just use Moq’s Verify method and you’ll see what I mean about clear failure messages:

[Test]
public void WhenCreatingAnOrderSaveTheCustomerDetails()
{
  const int orderCreatedByPersonId = 1;

  var customerServiceMock = new Mock<ICustomerService>();

  var orderService = new OrderService(customerServiceMock.Object);
  orderService.CreateOrder(new Order { FirstName = "John", LastName = "Smith", OrderItems = new List<OrderItem>() }, orderCreatedByPersonId);

  customerServiceMock.Verify(x => x.Save(It.Is<Customer>(y => y.FirstName == "John" && y.LastName == "Smith"), orderCreatedByPersonId));
}

And this is the error you’ll see:

Moq.MockException :
Expected invocation on the mock at least once, but was never performed: x => x.Save(It.Is<Customer>(y => y.FirstName == "John" && y.LastName == "Smith"), 1)
No setups configured.

Performed invocations:
ICustomerService.Save(Customer, 1)

I don’t like this error message. You can’t tell what caused the failure. You can see that ICustomerService.Save was called with a Customer object (and the number 1), bit you can’t see why the test failed.

You could split up the Verify – use two verify calls to help pinpoint where it has failed:

[Test]
public void WhenCreatingAnOrderSaveTheCustomerDetails_SplitVerify()
{
  const int orderCreatedByPersonId = 1;

  var customerServiceMock = new Mock<ICustomerService>();

  var orderService = new OrderService(customerServiceMock.Object);
  orderService.CreateOrder(new Order { FirstName = "John", LastName = "Smith", OrderItems = new List<OrderItem>() }, orderCreatedByPersonId);

  customerServiceMock.Verify(x => x.Save(It.Is<Customer>(y => y.FirstName == "John"), orderCreatedByPersonId));
  customerServiceMock.Verify(x => x.Save(It.Is<Customer>(y => y.LastName == "Smith"), orderCreatedByPersonId));
}

And this is the error you’ll see. It is a lot better as you now know exactly which part of the verify call failed (i.e. the last name of the customer).

Moq.MockException :
Expected invocation on the mock at least once, but was never performed: x => x.Save(It.Is<Customer>(y => y.LastName == "Smith"), 1)
No setups configured.

Performed invocations:
ICustomerService.Save(Recommendations.Customer, 1)

Now let’s use callbacks instead t give you a much more obvious error message. In your arrange part of the test, you set up a callback to catch the data sent to the mocked dependency:

[Test]
public void WhenCreatingAnOrderSaveTheCustomerDetails_UsingCallbacks()
{
  const int orderCreatedByPersonId = 1;

  var customerServiceMock = new Mock<ICustomerService>();
  Customer actualCustomer = null;
  int actualSavedBy=0;
  customerServiceMock.Setup(x => x.Save(It.IsAny<Customer>(), It.IsAny<int>())).Callback<Customer,int>((customer, person) =>
                              {
                               actualCustomer = customer;
                               actualSavedBy = person;
                              }); //set up the callback to catch the parameters sent to Save()

  var orderService = new OrderService(customerServiceMock.Object);
  orderService.CreateOrder(new Order { FirstName = "John", LastName = "Smith", OrderItems = new List<OrderItem>()},orderCreatedByPersonId);

  actualSavedBy.Should().Be(orderCreatedByPersonId);
  actualCustomer.Should().NotBeNull();
  actualCustomer.FirstName.Should().Be("John");
  actualCustomer.LastName.Should().Be("Smith");
}

Now you’ll see a much nicer error message (from Fluent Assertions):

Expected string to be "Smith", but "John" is too short.

Posted in .NET, Moq, Test Driven Development | Tagged: , , | 1 Comment »

How much TDD is enough TDD?

Posted by Kash Farooq on June 14, 2013

[We had a discussion at my current client about the right-level of TDD for a project under tight deadlines. This post is adapted from my contribution to that discussion]

I’ll start by stating that I am a huge fan of Test Driven Development.

I was introduced to TDD in 2005, “got it” straight away and now, 8 years later, would not want to program without it.

I’m not going to go into the benefits of TDD in this post. There are plenty of other blog posts out there that discuss that. Basically, as I said, I’m a fan – I’ve seen how easy it is to make changes to a well crafted TDD project and I would recommend TDD as a programming and design methodology to anyone that will listen.

However…would I aim for 100% code coverage on a project? I’m not sure. You have to be pragmatic. When you have project specific time constraints, you have to look at the value that each unit test is adding. 

Consider a really light MVC controller action:

  1. Call a service.
  2. Use AutoMapper to map the response from a service contract to an identical view model.
  3. Return a View.

You may have dozens of controller actions like this. And for experienced developers, this three line method probably doesn’t need a unit test.  There is no functionality to be described by the unit test. Your unit test is not adding any value. It is probably just going to replicate the implementation (and take more lines of code to do that replication). The test isn’t going to catch any accidentally introduced bugs as… well… it would be hard to introduce a bug without breaking it completely. And if you are changing a controller action, you’re going to hit it manually before you commit your change to source control, right?

Having said this, you also have to consider the skill and experience level of the team.

If I was mentoring someone new to TDD, or new to doing C# “properly”, I’d want them to do it 100% TDD. They shouldn’t write a line of production code without first writing the test. I would expect to see a unit test for that controller action example above.

But if your team is experienced, with developers who know how to do TDD, a test for the above method is probably overkill.

Forcing TDD on a novice developer has other benefits – it’s not just about teaching them how to do TDD. It forces developers to keep their classes small and targeted. Experienced developers should know all about SOLID. They shouldn’t need TDD to force their code to be clean and their classes to be targeted. It should be second nature.

So, when should an experienced developer do TDD?

How about if your MVC controller action was a bit fatter:

  1. Call a service.
  2. Get some data from it and call another service with that data.
  3. Conditionally manipulate/merge the data into one view model.
  4. Return a view dependent on what the model looks like.

Now, ignoring that this controller action may be doing too much, you definitely need to do this work TDD. There is sufficient logic that could be buggy, or could become buggy. Also, if your controller started as a simple 3 liner, but is starting to do more – now you do need to add a test.

Other example situations:

  • Is the code going to re-used? If so, do it TDD.
  • Is there functionality that needs documenting? A unit test with a suitable name can describe what functionality is being implemented  – it provides accurate documentation rather than comments or documents that seem to be out of date a few days after they were written. And, obviously, you have a unit test ensuring that the functionality is working.

So, the “do I need to do TDD” questions could be:

  • Is there sufficient logic that I will need to write that could be buggy? Do you have an if statement, or a loop or some other logic?
  • Is this code going to be re-used?
  • Is this code an API?
  • Is it not obvious what the code is doing?
  • Do you want to explain some functionality, or business rule, to a developer that might be looking at this code in the future?

If the answer to any of these questions is “yes”, you probably need to write a test first.

If the answer is “no”, and your code is as simple as the controller action example I gave at the start…you probably don’t need a test. But: you should have some UI-based integration tests (e.g. using something like Selenium Webdriver/Coypu) that get run by your Continuous Integration solution to make sure the system hangs together after each commit.

However…

These aren’t hard and fast rules. There are other factors to take into consideration.

Is the team a a mixture of experienced and novice developers? Well, you can’t have one rule for one, and one for the another! Especially if everyone is going to work on all parts of the system.

Is the code going to be handed over to another team? Then you’d better do it TDD.

Perhaps these two scenarios mean you will always need to write tests for everything and my whole post is pointless!

Related posts

Posted in Test Driven Development | Tagged: , | Leave a Comment »

More TDD with wrapper classes

Posted by Kash Farooq on June 23, 2012

I have previously blogged about using wrapper classes to test the hard to test. In that post I made things easy for myself by using the parameterless constructor of the SmtpClient class.

I thought I’d revisit this area of testing, and try something different. This time I’ve used Moq rather than Rhino Mocks for starters. But I’m also going to pretend that SmtpClient does not have a parameterless constructor.  If a class you need to make testable does not have a parameterless constructor, it makes things a bit trickier:

public class SystemUnderTest
{
  public void MethodToBeTested()
  {
    var mailMessage = new MailMessage { Subject = "Hello", From = new MailAddress("Me@Me.com") };
    mailMessage.To.Add(new MailAddress("You@You.com"));
    var smtpClient = new SmtpClient("smtp.kashfarooq.com", 25);
    smtpClient.Send(mailMessage);
  }
}

A number of things in the above code need to be addressed and tested. The SMTP client is being instantiated in the method with the host and port being sent in via a the constructor, which makes things awkward to test. Apart from that complication, I’d like to make sure the correct host and port are being used. And I’d also like to make sure the correct details are being set in the MailMessage object.

First, we need an interface so we can mock the Send method. This matches the SmtpClient.Send method exactly:

public interface ISmtpClient
{
  void Send(MailMessage mailMessage);
}

We also need a wrapper class that will wrap SmtpClient and the constructor we are planning to use:

public class SmtpClientWrapper : SmtpClient, ISmtpClient
{
  public SmtpClientWrapper(string host, int port) : base(host, port)  { }
}

The above wrapper class inherits the interface defined above and the class we are trying to make testable: SmtpClient. And as it derives from SmtpClient, it automatically implements ISmtpClient.Send(MailMessage).

Next, we’ll create a suitable constructor for our SystemUnderTest class so that we can inject in some mocks. Because the MethodToBeTested creates the SmtpClient object, I’m going to use the “Using a Func instead of a Factory” trick:

private readonly Func<string, int, ISmtpClient> createSmtpClient;

public SystemUnderTest(Func<string, int, ISmtpClient> createSmtpClient)
{
  this.createSmtpClient = createSmtpClient;
}

public SystemUnderTest() : this((host,port) => new SmtpClientWrapper(host, port)) {}

So, what’s going on here? I have created a Func that will take a string and int (the host and port) and return an ISmtpClient. From my test I’ll use the first constructor. The production code will use the second constructor. In both cases, the Func supplied is stored in createSmtpClient – and this will be called from MethodToBeTested to actually create the SmtpClient.

I’m now in full control of all the dependencies. I can catch the MailMessage parameter sent to the Send method, and the host and port name sent to the createSmtpClient Func, which ultimately gets sent to to the SmtpClient(string host, int port) constructor.

And here is the test that creates a mock ISmtpClient and a Func that returns it, and also catches the parameters sent to it so the appropriate asserts can be done:

[Test]
public void CorrectEmailSentViaTheCorrectSmtpHost()
{
  string actualHostName=string.Empty;
  int actualPort=0;
  MailMessage actualMailMessage = null;

  var mockSmtpClient = new Mock<ISmtpClient>();
  mockSmtpClient
     .Setup(x => x.Send(It.IsAny<MailMessage>()))
     .Callback((MailMessage message) => actualMailMessage = message); //Catch the MailMessage sent to the Send method

  //Func to return an ISmtpClient and catch data sent to it
  Func<string, int, ISmtpClient> createSmtpClient = (host, port) =>
      {
         actualHostName = host; //catch the hostname used
         actualPort = port; //catch the port used
         return mockSmtpClient.Object; //return mocked SmtpClient
  };

  //Call system under test
  var sut = new SystemUnderTest(createSmtpClient);
  sut.MethodToBeTested();

  //Asserts
  actualHostName.Should().Be("smtp.kashfarooq.com");
  actualPort.Should().Be(25);
  actualMailMessage.Subject.Should().Be("Hello");
  actualMailMessage.From.Address.Should().Be("Me@Me.com");
  actualMailMessage.To[0].Address.Should().Be("You@You.com");
}

[Incidentally, I’m using the excellent FluentAssertions in my asserts.]

Posted in .NET, Moq, Test Driven Development | Tagged: , , , | Leave a Comment »