How to Test your Production Code: Using Test Stubs

In our last post we explored how to use Dummy Objects in order to test our code when we are dealing with objects that are difficult to create. One important restriction on the usage of this kind of test double is that we have to avoid touching the dummy object during our tests. We can easily check that LoadInvoicesByDate throws when from is higher that threshold:

public string WarningMessage;
public IList<Invoice> Invoices;
public void LoadInvoicesByDate(DateTime from, DateTime to, DateTime threshold, IDbFactory dbFactory)
{
  if (from > threshold)
    throw new DateOverThresholdException("from");

  var count = dbFactory.CountInvoices(from, to);
  if (count == 0)
  {
    WarningMessage = "No Invoices in given rage";
    return;
  }
  Invoices = dbFactory.GetInvoices(from, to);
}

But what happens if we have to pass the first ‘if’ and check that the text of WarningMessage is updated when count equals zero?

In this case the variable count is said to be an indirect input of the code we want to test and in order to control it’s value we need to instantiate a special version of dbFactory that we have under our control. Of course we don’t want to use the real instance of DbFactory because who knows the state of the database… we could never get a count that equals 0. So in our test we are going to need a Test Double called, you guessed it, Test Stub.

The Test Stub will provide you with the indirect input you need no matter what how it gets called. Let’s explain with a test that checks  that the WarningMessage field is set when dbFactory.CountInvoices returns zero:

private class DbFactoryStub : IDbFactory
{
  public int CountInvoices(DateTime from, DateTime to)
  {
    return 0;
  }
  // other IDbFactory methods
}
[Test]
public void WarningMessageWhenCountIsZero()
{
  IDbFactoy dbFactory = new DbFactoryStub();
  invoicesManager.LoadInvoicesByDate(
      DateTime.Now, DateTime.Now, DateTime.Now,
      dbFactory);
  Assert.AreEqual("No Invoices in given rage",
                  invoicesManager.WarningMessage);
}

What’s happening here?

First I create a new class that implements IDbFactory and set the return value of CountInvoices to zero, which is exactly the return value we want to have. With this test double we are forcing our code through a path that could have been difficult to simulate with the real implementation.

Moreover, we can generalize a bit our dummy class and set the wanted return values in the tests

private class DbFactoryDummy : IDbFactory
{
  public int DummyInvoicesCount;
  public IList<Invoice> DummyInvoices;
  public int CountInvoices(DateTime from, DateTime to)
  {
    return DummyInvoicesCount;
  }
  public IList<Invoice> GetInvoices(DateTime from, DateTime to)
  {
    return DummyInvoices;
  }
}

[Test]
public void WarningMessageWhenCountIsZero()
{
  IDbFactoy dbFactory = new DbFactoryDummy();
  dbFactory.DummyInvoicesCount = 0;
  invoicesManager.LoadInvoicesByDate(
      DateTime.Now, DateTime.Now, DateTime.Now,
      dbFactory);
  Assert.AreEqual("No Invoices in given rage",
                  invoicesManager.WarningMessage);
}

[Test]
public void InvoicesSetGetInvoicesReturnedValue()
{
  IDbFactoy dbFactory = new DbFactoryStub();
  dbFactory.DummyInvoicesCount = 1;
  dbFactory.DummyInvoices = new List<Invoice> { new Invoice() };
  invoicesManager.LoadInvoicesByDate(
      DateTime.Now, DateTime.Now, DateTime.Now,
      dbFactory);
  Assert.AreEqual(string.Empty,
                  invoicesManager.WarningMessage);
  Assert.AreEqual(dbFactory.DummyInvoices,
                  invoicesManager.Invoices);
}

With this change to DbFactoryDummy we are able to configure its return values while testing in order to use the same dummy class for different test cases.

Remember that our goal isn’t that of testing the behaviour of the particular implementation of DbFactory but how our code behaves when stimulated with different indirect inputs.

What if we want to test the indirect outputs of the system? for that we use Mock Objects, that will be explained in the next post.

Advertisements

2 thoughts on “How to Test your Production Code: Using Test Stubs

  1. Pingback: How To Test Your Production Code: Test Spy – Code cleaners

  2. Pingback: How to Test your Production Code: Everything You Need To Know About Test Doubles – Code cleaners

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s