REST using the WCF Web API – getting RESTful the BDD way (Part 4)

Written on April 20, 2011

Postings published on this series so far:

RESTless testing

Not only does REST become more and more important but also Test Driven Development (TDD) has become state of the art in professional software development.

A less common "sub type" of TDD is Behavior Driven Development (BDD) which is a agile software development technique that encourages collaboration between developers and non-developers.

BDD is focused on a better understanding of the software to be written by discussing with stakeholders in their natural language combined with the so called ubiquitous language of the stakeholders problem domain.

Yet there are a lot of BDD frameworks available for .NET . The one I like most of them is Machine.Specifications (short: MSpec) with the newish Machine.Fakes (short: MFakes) on top which allows a lean way of BDD by providing an integration layer between MSpec and different Mock/Fake/Substitute frameworks such as Rhino.Mocks or Moq and others. Thus Machine.Fakes simplifies the usage of these frameworks on top of MSpec.

To cut a long story short, lets write the first test.

As you may already suspect: Machine.Fakes is available on NuGet by adding a Package Library Reference to "Machine.Fakes.RhinoMocks":

Machine.Fakes on Nuget

As you can see, there are also implementations available for FakeItEasy, Moq and NSubstitute.

Choosing "Machine.Fakes.RhinoMocks" installs all required dependencies to our project and we're ready to enjoy the magic of Machine.Fakes.

As we haven't tested the Get method of our ContactsResource until now, we'll catch up on this.

Here's the test code (we prefer to speak of "specifications" in MSpec):

public class Given_a__ContactsResource__when_requesting_all_contacts : WithSubject<ContactsResource> {
    static List<Contact> _actualContacts;

    Establish context = () => {
        With<TheMicrosoftGangContactList>();
        With(new FakeContactRepository(The<IList<IContact>>()));
    };

    Because of
        = () => {
                _actualContacts = Subject.Get();
            };

    It should_return_the_microsoft_gang 
        = () =>
                   {
                       _actualContacts.Count.ShouldEqual(3);
                };
}

The result of the specification being run in the ReSharper test runner:

Resharper test runner result

Now let's see what happened in detail.

BDD and thus MSpec follows the AAA syntax for unit tests which means that tests are run in the following order:

  • Arrange

  • Act

  • Assert

Whereas in BDD we use the terms

  • Given

  • When

  • Then

which are mapped to the following methods of MSpec:

  • Establish (context)

  • Because (of)

  • It (should something)

The name of the test class is mapped to the name of the test inside the test runner and the name of the It-delegate is mapped to the assertion description inside the test runner. Also the underscores in class and delegate name have been replaced by white spaces in order to improve readability for non-developers.

As you can see, our class derives from WithSubject which allows us to work with so called BehaviorConfigs. BehaviorConfigs are classes you can implement to set up dependencies for our system under test (a.k.a. SUT, called Subject in Machine.Fakes terminology).

You can use an arbitrary number of BehaviorConfigs inside your test class.

Using the With() or With(new BehaviorConfig()) method inside the Establish delegate Machine.Fakes is told to use them.

The reasonable question at this point is: what's the use?

As you may remember from the previous posting, our ContactsResource has a dependency on the IContactRepository which handles the CRUD operations on the database.

When it comes to testing our ContactsResource, we don't want to setup a database having the proper test data ready every time we want to run our tests.

Besides that we don't want to test our ContactRepository (which would be the case if it were the concrete implementation when testing the ContactsResource) -- we just want to rely on a ContactRepository working properly instead.

The way to get rid of the concrete ContactRepository implementation is the usage of Mocks or Stubs and so the circle is complete.

Mocks/Stubs (or in terms of Machine.Fakes: Fakes) created the Machine.Fakes way are set up inside the BehaviorConfigs (or directly inside the Establish delegate method) to be reusable and keep the Establish method body short and clear.

In order to test our ContactsResource without having a dependency on a concrete ContactRepostory implementation we will use two Fakes:

  • FakeContactRepository, which returns a concrete list of contacts when calling it's Get method

  • TheMicrosoftGangContactList which is the concrete list of three contacts being return form the Get method of the FakeContactRepository

Now lets take a look inside the TheMicrosoftGangContactList BehaviorConfig:

public class TheMicrosoftGangContactList {
    OnEstablish context =
        fakeAccessor
        => {
            List<IContact> contacts =
                   new List<IContact>()
                       {
                           new Contact()
                               {
                                   Id = 1,
                                   Name = "Glenn Block"
                               },
                           new Contact()
                               {
                                   Id = 2,
                                   Name = "Scott Hanselman"
                               },
                           new Contact()
                               {
                                   Id = 3,
                                   Name = "Scott Guthrie"
                               }
                       };
            fakeAccessor.Configure(
                   config => config
                               .For<IList<IContact>>()
                               .Use(() => contacts));
        };
}

Most of it is similar to the code from the previous parts of the post series.

The main improvement is the OnEstablish delegate whose parameter fakeAccessor is _Configure_d to Use our list called contacts For any request on IList. OnEstablish then is executed in the Establish delegate method of our test class later on.

This is the magic of BehaviorConfigs explained in about three words. Did you notice by the way, that you don't have to implement anything to get this to work?

Yet, there's another BehaviorConfig called FakeContactRepository which is passed into the test class by the second form of With by using parameters. In addition FakeContactRepository itself has a parameter of type IList. At closer inspection you should notice that the call of IList is surrounded by the The<>() method. The intention behind this method is to get a singleton mock for the given type in the context of our test class. By Configure-ing our IList mock to return the contacts list in the TheMicrosoftGangContactList BehaviorConfig we'll get back the contacts list now by calling The(). This is nice, isn't it?

But there's more to come: Machine.Fakes has to other methods allowing us to handle mock objects with ease:

  • An returns an arbitrary mock object which can be configured by our needs.

  • Some() with it's overload Some(int amount) allow us to create_IList_s of the required types where the latter gives us the ability to set the number of objects being held inside the list. Some(3) could also be used instead of our TheMicrosoftGangContactList BehaviorConfig.

Both methods of course are available also inside BehaviorConfigs through the fakeAccessor.

At least, lets take a look at our FakeContactRepository implemenation:

public class FakeContactRepository {
    static IList<IContact> _contacts;

    public FakeContactRepository(IList<IContact> contacts) {
        _contacts = contacts;
    }

    OnEstablish context =
        fakeAccessor
        => {
            IContactRepository repository = fakeAccessor.An<IContactRepository>();
            repository.WhenToldTo(r => r.Get())
                   .Return(_contacts);
            fakeAccessor.Configure(
                   config=>config.For<IContactRepository>().Use(()=>repository));
        };
}

This one looks very similar to the previous BehaviorConfig. Please notice the call of the WhenToldTo and the Return extension methods on the repository instance. These allow us to configure the behavior of the mock object (which means here: returning the list of contacts being passed into it before).

Of course there are more than these two methods -- further details can be found in the extensive list of samples being include in the Machine.Fakes download.

This posting has been a little bit out of band concerning WCF Web API but hopefully not less interesting.

Now that we have set up our infrastructure in terms of IoC and testing we can continue the RESTful journey through the Microsoft WCF Web API in the next part of this series.

Postings published on this series so far:

DotNetKicks-DE Image.aspx&bgcolor=3169AD&fgcolor=FFFFFF&border=000000&cbgcolor=D4E1ED&cfgcolor=000000)