Click here to monitor SSC
  • Av rating:
  • Total votes: 7
  • Total comments: 0
Michael Sorens

A TDD Journey: 6- Mini-Factory Pattern; Don’t Care Terms

01 August 2014

Michael Sorens wraps up his TDD journey by discussing a number of tools and techniques, such as the mini-factory design pattern and the 'don’t care' capability, that can be used in  TDD (Test-Driven Development)t to increase the likelihood that you can approach 100% code-coverage. 

 

Part 1: Trials and Tribulations of TDD

 

Part 2: Naming Tests; Mocking Frameworks; Dependency Injection

 

Part 3: Mocks vs. Stubs; Test Frameworks; Assertions; ReSharper Accelerators

 

Part 4: Tests as Documentation; False Positive Results; Component Isolation

 

Part 5: Tests vs. Code; Refactor Friendliness; Test Parameterization

Part 6: Mini-Factory Pattern; Don’t Care Terms

This is part 6 of our exploration into practicing hands-on TDD. Unlike most of my multi-part series, it is not advisable to join this one in the middle. So if you are arriving fresh, please go back and review part 1 for an overview of TDD and subsequent parts that both built out our tests & code and introduced ancillary concepts and techniques crucial to the TDD approach.

Here is a summary of the behaviors we have implemented for our WidgetActivator thus far:

WidgetActivatorTest:

        Execute_returns_false_when_loading_fails_and_then_publishing_succeeds

        Execute_returns_true_when_loading_succeeds_and_then_publishing_succeeds

        Execute_returns_false_when_publishing_fails_after_loading_succeeds

        Execute_returns_true_when_publishing_succeeds_after_loading_succeeds

        Execute_only_publishes_if_loading_succeeds

Hearken back to part 1 for a discussion of how test-driven development is just behavior-driven development in disguise. Thinking of tests as behaviors instead, it is much easier to decide what code to write next: what is the next most important behavior your system needs to be able to do? Let’s take a look.

TEST: The loader and publisher are barebones, so far, not actually being given any data to process. So let’s first introduce an IAddressProvider—by way of a test, of course!—to provide an address from which the loader will load. (This whole test is new, of course, so I am highlighting the significant portions here.)

 

[Test]

public void Execute_gets_an_address_from_which_to_load_a_widget()

{

    var mockAddressProvider = new Mock<IAddressProvider>();

    var stubWidgetLoader = Mock.Of<IWidgetLoader>();

    var stubWidgetPublisher = Mock.Of<IWidgetPublisher>();

    var activator = new WidgetActivator(

stubWidgetLoader, stubWidgetPublisher, mockAddressProvider.Object);

 

    activator.Execute();

 

    mockAddressProvider.Verify(x => x.GetAddress()Times.Once());

}

 

 

CODE: There are several compile errors here. First we need to create the IAddressProvider interface containing a GetAddress method.

 public interface IAddressProvider

{

    void GetAddress();

}

We then need to adjust the WidgetActivator to accept an IAddressProvider. That is done with a single keystroke using ReSharper, as was demonstrated in part 3:

But attempting to apply that quick fix, ReSharper then asks me what to do about the current uses of the constructor—it is used, in fact, in all of our tests:

ReSharper gives you a choice of actions for each one, but often none of those choices is ideal. Whichever you choose, you likely have to revisit each test method and redress it. You saw this already when we went from a one-argument constructor to a two-argument constructor. It is more cumbersome to deal with going yet again to a three-argument constructor. So let’s take a look at a different approach, a useful design pattern to make this much less painful.

For the moment I am going to leave the constructor as a two-argument constructor, and comment out the new test so the existing code will compile. That way the refactoring I am about to do can be easily checked for integrity (by ensuring all current tests still pass when done).

//public void Execute_gets_an_address_from_which_to_load_a_widget()

//{

//    var mockAddressProvider = new Mock<IAddressProvider>();

//    var stubWidgetLoader = Mock.Of<IWidgetLoader>();

//    var stubWidgetPublisher = Mock.Of<IWidgetPublisher>();

//    var activator = new WidgetActivator(

// stubWidgetLoader, stubWidgetPublisher, mockAddressProvider.Object);

//

//    activator.Execute();

//

//    mockAddressProvider.Verify(x => x.GetAddress(), Times.Once());

//}

 Mini-Factory Pattern

I am going to introduce a mini-factory to create WidgetActivators in the form of a single method in the test class (it is the last method in the code sample below). The mini-factory lets you supply an WidgetLoader and an IWidgetPublisher but allows both to be optional. If you do not supply one, a simple stub is automatically used in its place. In the code here, I have commented out rather than deleting deprecated lines so you can see the “before” and “after”. So here is the entire test class, with the mini-factory, CreateWidgetActivator, in place:

public class WidgetActivatorTest

{

    [Test]

    public void Execute_returns_false_when_loading_fails_and_then_publishing_succeeds()

    {

     //var stubWidgetLoader = Mock.Of<IWidgetLoader>();

        var stubWidgetPublisher = Mock.Of<IWidgetPublisher>(

            x => x.Publish() == true

            );

        //var activator = new WidgetActivator(stubWidgetLoader, stubWidgetPublisher);

        var activator = CreateWidgetActivator(widgetPublisher: stubWidgetPublisher);

 

        var result = activator.Execute();

 

        Assert.That(result, Is.False);

    }

    [Test]

    public void Execute_returns_true_when_loading_succeeds_and_then_publishing_succeeds()

    {

        var mockWidgetLoader = new Mock<IWidgetLoader>();

        mockWidgetLoader

            .Setup(x => x.Load())

            .Returns(() => true);

        var stubWidgetPublisher = Mock.Of<IWidgetPublisher>(

            x => x.Publish() == true

            );

        //var activator = new WidgetActivator(mockWidgetLoader.Object, stubWidgetPublisher);

        var activator = CreateWidgetActivator(mockWidgetLoader.Object, stubWidgetPublisher);

 

        var result = activator.Execute();

 

        Assert.That(result, Is.True);

    }

    [Test]

    public void Execute_returns_false_when_publishing_fails_after_loading_succeeds()

    {

        var mockWidgetPublisher = new Mock<IWidgetPublisher>();

        mockWidgetPublisher

           .Setup(x => x.Publish())

           .Returns(() => false);

        var stubWidgetLoader = Mock.Of<IWidgetLoader>(

            x => x.Load() == true

         );

        //var activator = new WidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

        var activator = CreateWidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

 

        var result = activator.Execute();

 

        Assert.That(result, Is.False);

    }

    [Test]

    public void Execute_returns_true_when_publishing_succeeds_after_loading_succeeds()

    {

        var mockWidgetPublisher = new Mock<IWidgetPublisher>();

        mockWidgetPublisher

            .Setup(x => x.Publish())

            .Returns(() => true);

        var stubWidgetLoader = Mock.Of<IWidgetLoader>(

            x => x.Load() == true

            );

        //var activator = new WidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

        var activator = CreateWidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

 

        var result = activator.Execute();

 

        Assert.That(result, Is.True);

    }

 

    [TestCase(true, 1)]

    [TestCase(false, 0)]

    public void Execute_only_publishes_if_loading_succeeds(bool loaderSuccess, int callCount)

    {

        var stubWidgetLoader = Mock.Of<IWidgetLoader>(

x => x.Load() == loaderSuccess

);

        var mockWidgetPublisher = new Mock<IWidgetPublisher>();

        //var activator = new WidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

        var activator = CreateWidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

 

        activator.Execute();

 

    mockWidgetPublisher.Verify(x => x.Publish(), Times.Exactly(callCount));

    }

 

    private WidgetActivator CreateWidgetActivator(

        IWidgetLoader widgetLoader = null,

        IWidgetPublisher widgetPublisher = null

        )

    {

        return new WidgetActivator(

            widgetLoader ?? Mock.Of<IWidgetLoader>(),

            widgetPublisher ?? Mock.Of<IWidgetPublisher>()

        );

    }

}

In the first test the loader was just a default mock object, which is now handled automatically by the factory so we no longer have to pass that in. But because we want to pass the second parameter while omitting the first, we use C#’s named arguments. This lets you specify any of the optional parameters by using its name:

        var activator = CreateWidgetActivator(widgetPublisher: stubWidgetPublisher);

The second test, on the other hand, needs both loader and publisher to behave a certain way so both are passed in. I still use the factory method, however, even though there is no savings in the test because it helps isolate the use of the WidgetActivator constructor to a single place in the test code, a good design practice. Similarly with the third and fourth tests. So there is not a lot of code reduction in the tests, but you will see the utility of this mini-factory in a moment.

TEST: Let’s re-introduce that new test we started to add before the interlude above, now within the context of this mini-factory. We introduce a new parameter to the factory method, an addressProvider, and that is the only one we care about, so we used a named argument.

[Test]

public void Execute_gets_an_address_from_which_to_load_a_widget()

{

    var mockAddressProvider = new Mock<IAddressProvider>();

    var activator = CreateWidgetActivator(addressProvider: mockAddressProvider.Object);

 

    activator.Execute();

 

    mockAddressProvider.Verify(x => x.GetAddress(), Times.Once());

}

TEST: Adding that parameter to the factory method still necessitates adjusting a signature, but this time it is the signature of the factory method in the test class. By just adding one line to the factory, all the other tests are still working:

private WidgetActivator CreateWidgetActivator(

    IWidgetLoader widgetLoader = null,

    IWidgetPublisher widgetPublisher = null,

    IAddressProvider addressProvider = null

    )

{

    return new WidgetActivator(

        widgetLoader ?? Mock.Of<IWidgetLoader>(),

        widgetPublisher ?? Mock.Of<IWidgetPublisher>()

    );

}

TEST: Now we can finally focus on the task of turning the red test to green. We start by hooking up the parameter we just added in the factory.

private WidgetActivator CreateWidgetActivator(

    IWidgetLoader widgetLoader = null,

    IWidgetPublisher widgetPublisher = null,

    IAddressProvider addressProvider = null

    )

{

    return new WidgetActivator(

        widgetLoader ?? Mock.Of<IWidgetLoader>(),

        widgetPublisher ?? Mock.Of<IWidgetPublisher>(),

        addressProvider ?? Mock.Of<IAddressProvider>()

    );

}

CODE: That causes a compile error, because the WidgetActivator constructor does not handle an IAddressProvider yet. Now applying ReSharper’s Add Parameter adjusts the constructor signature to accept the parameter.

public WidgetActivator(

    IWidgetLoader widgetLoader,

    IWidgetPublisher widgetPublisher,

    IAddressProvider addressProvider)

{

    _widgetLoader = widgetLoader;

    _widgetPublisher = widgetPublisher;

}

CODE: Applying ReSharper’s Introduce and initialize field on that parameter makes that parameter available within the class.

public class WidgetActivator

{

     private readonly IWidgetLoader _widgetLoader;

     private readonly IWidgetPublisher _widgetPublisher;

     private readonly IAddressProvider _addressProvider;

     public WidgetActivator(

         IWidgetLoader widgetLoader,

         IWidgetPublisher widgetPublisher,

         IAddressProvider addressProvider)

     {

         _widgetLoader = widgetLoader;

         _widgetPublisher = widgetPublisher;

         _addressProvider = addressProvider;

     }

}

 

With this last tweak we now have code that compiles. And reviewing all tests shows just one that is failing—the very test we are working on.

Add a call to the GetAddress method on the IAddressProvider interface to make the test go green:

public bool Execute()

{

    _addressProvider.GetAddress();

    var success = _widgetLoader.Load();

    if (success)

    {

        success &= _widgetPublisher.Publish();

    }

    return success;

}

But the test passing is not the most interesting point here. The factory method was implemented to achieve two particular goals: centralize the call to the WidgetActivator constructor to a single spot and provide defaults for all dependencies. Those two together mean that (a) adding dependencies to the signature of that constructor needs to happen in just one place, and (b) calls to the factory do not have to change to accommodate new dependencies to the constructor. The net result: you do not have to edit some or even all of your previous tests, as you would have to without the factory.

TEST: So we have an address; now we need to use it.

[Test]

public void Execute_uses_an_address_to_load_widget()

{

    var expectedAddress = "test address";

    var stubAddressProvider = Mock.Of<IAddressProvider>(

        x => x.GetAddress() == expectedAddress);

    var mockWidgetLoader = new Mock<IWidgetLoader>();

    var activator = CreateWidgetActivator(

        mockWidgetLoader.Object,

        addressProvider: stubAddressProvider);

 

    activator.Execute();

 

    mockWidgetLoader.Verify(x => x.Load(expectedAddress), Times.Once);

} 

CODE: To allow the above to compile, first we need to adjust the IAddressProvider interface to return a value from the GetAddress method.

 

public interface IAddressProvider

{

    string GetAddress();

}

 

CODE: Then we need to adjust the WidgetLoader interface to accept a value in the Load method.

public interface IWidgetLoader

{

    bool Load(string address);

}

TEST: That last change will, however, cause repercussions in several other tests that we must go back to fix before the compile completes. In these other tests we do not care what was passed to the Load method so specify a “don’t care” with It.IsAny. Here is a fix to one of the tests; the others require the same update:

[Test]

public void Execute_returns_true_when_loading_succeeds_and_then_publishing_succeeds()

{

    var mockWidgetLoader = new Mock<IWidgetLoader>();

    mockWidgetLoader

        .Setup(x => x.Load(It.IsAny<string>()))

        .Returns(() => true);

    var stubWidgetPublisher = Mock.Of<IWidgetPublisher>(

        x => x.Publish() == true

        );

    var activator = CreateWidgetActivator(mockWidgetLoader.Object, stubWidgetPublisher);

 

    var result = activator.Execute();

 

    Assert.That(result, Is.True);

}

CODE: Finally, the class under test must also be modified to satisfy our new test:

public bool Execute()

{

    var address = _addressProvider.GetAddress();

    var success = _widgetLoader.Load(address);

    if (success)

    {

        success &= _widgetPublisher.Publish();

    }

    return success;

}

And that brings us back to all tests passing:

 Don’t Care Terms

We introduced the “don’t care” term in a moq SetUp call just above: It.IsAny<string>(). But such “don’t care” terms are not restricted to just SetUp calls. They may be used in most any Moq method. In this latest test case we verified that a method was called with a specific value that was passed in. But another common case is verifying that a method was called at all, regardless of the arguments. That is, instead of this:

mockWidgetLoader.Verify(x => x.Load(expectedAddress), Times.Once);

…you might just use this if desired:

mockWidgetLoader.Verify(x => x.Load(It.IsAny<string>()), Times.Once);

And you are not limited to simple, built-in types with It.IsAny; it is a standard generic type It.IsAny<T> so you could use your complex objects (It.IsAny<MyContractType>) or even your own generic types (It.IsAny<MyDetail<MyContractType>>). For cases where your type may be unwieldy you could even use  something like It.IsAny<object> or It.IsAny<object[]>.

TEST: Just as the loader needs an address, so does the publisher. Notice that for the WidgetLoader here I use a “don’t care” because this test is about the WidgetPublisher.

[Test]

public void Execute_uses_an_address_to_publish_widget()

{

    var expectedAddress = "test address";

    var stubAddressProvider = Mock.Of<IAddressProvider>(

        x => x.GetAddress() == expectedAddress);

    var stubWidgetLoader = Mock.Of<IWidgetLoader>(

        x => x.Load(It.IsAny<string>()) == true);

    var mockWidgetPublisher = new Mock<IWidgetPublisher>();

    var activator = CreateWidgetActivator(

        stubWidgetLoader,

        mockWidgetPublisher.Object,

        stubAddressProvider);

 

    activator.Execute();

 

    mockWidgetPublisher.Verify(x => x.Publish(expectedAddress), Times.Once);

}

CODE: To get that to compile we modify the Publish method on the interface to take a parameter.

 

public interface IWidgetPublisher

{

    bool Publish(string address);

}

TEST: That, however, breaks several tests that were not expecting a parameter. We go back and introduce a “don’t care” in those tests, be it in the SetUp method or the Verify method. Here are two of the four tests that need the patch.

 

[Test]

public void Execute_returns_true_when_loading_succeeds_and_then_publishing_succeeds()

{

    var mockWidgetLoader = new Mock<IWidgetLoader>();

    mockWidgetLoader

        .Setup(x => x.Load(It.IsAny<string>()))

        .Returns(() => true);

    var stubWidgetPublisher = Mock.Of<IWidgetPublisher>(

        x => x.Publish(It.IsAny<string>()) == true

        );

    var activator = CreateWidgetActivator(mockWidgetLoader.Object, stubWidgetPublisher);

 

    var result = activator.Execute();

 

    Assert.That(result, Is.True);

}

 

[TestCase(true, 1)]

[TestCase(false, 0)]

public void Execute_only_publishes_if_loading_succeeds(bool loaderSuccess, int callCount)

{

    var stubWidgetLoader = Mock.Of<IWidgetLoader>(x => x.Load(It.IsAny<string>()) == loaderSuccess);

    var mockWidgetPublisher = new Mock<IWidgetPublisher>();

    var activator = CreateWidgetActivator(stubWidgetLoader, mockWidgetPublisher.Object);

 

    activator.Execute();

 

    mockWidgetPublisher.Verify(x => x.Publish(It.IsAny<string>()), Times.Exactly(callCount));

}

CODE: Finally, we introduce the parameter in the class under test, giving us a clean compile again, as well as the new test (Execute_uses_an_address_to_publish_widget) now passing.

public bool Execute()

{

    var address = _addressProvider.GetAddress();

    var success = _widgetLoader.Load(address);

    if (success)

    {

        success &= _widgetPublisher.Publish(address);

    }

    return success;

}

Adding the mini-factory design pattern and the don’t care capability to test parameterization, ReSharper quick fixes, and the other tools and techniques amassed thus far, you should have quite the arsenal to assist your own TDD development efforts. What is most fascinating about TDD to me is this: looking at the Execute method just above, every token is there to satisfy a test. There is no fat, no excess. We have, by the nature of TDD, 100% coverage for this code. Note, however, that I am not claiming that 100% code coverage is always easy or practical. But you do have complete coverage for those bits that you can build with TDD. If you found this TDD series useful, be sure to spread the word! If interest warrants, there is always more to explore: code coverage, refactoring, arrange-act-assert, equivalence partitioning, boundary value analysis, queuing theory, and more…

Michael Sorens

Author profile:

Michael Sorens is passionate about software to be more productive, evidenced by his open source libraries in several languages (see his API bookshelf) as well as SqlDiffFramework (a DB comparison tool for heterogeneous systems including SQL Server, Oracle, and MySql). With degrees in computer science and engineering he has worked the gamut of companies from Fortune 500 firms to Silicon Valley startups over the last 25 years or so. Current passions include PowerShell, .NET, SQL, and XML technologies (see his full brand page). Spreading the seeds of good design wherever possible, he enjoys sharing knowledge via writing (see his full list of articles), teaching, and StackOverflow. Like what you have read? Connect with Michael on LinkedIn and Google +

Search for other articles by Michael Sorens

Rate this article:   Avg rating: from a total of 7 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.
 

Top Rated

R Basics
 For exploring data and doing open-ended statistical analysis on it, nothing beats the R language. Over... Read more...

R Basics
 For exploring data and doing open-ended statistical analysis on it, nothing beats the R language. Over... Read more...

Rethinking the Practicalities of Recursion
 We all love recursion right up to the point of actually using it in production code. Why? Recursion... Read more...

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Build and Deploy a .NET COM Assembly
 Phil Wilson demonstrates how to build and deploy a .NET COM assembly using best practices, and how to... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.