Given, when, then and examples for classes

Some of us have taken to writing comments in our BDD classes to give us Given, When, Then at a unit level.

So, if I’m writing examples for a cowhand, I might write something like this:


public class CowhandTest {

public void shouldMilkTheCow() {

// Given a repository which knows about one cow
CowRepository shed = mock(CowRepository.class);
Cow daisy = mock(Cow.class);
stub(shed.getCowByName("Daisy")).toReturn(daisy);

// Given a cowhand who knows where the cows are kept
Cowhand cowhand = new Cowhand(shed);

// When I ask the cowhand to milk the cow
cowhand.milkCow("Daisy");

// Then the cow should have been milked
verify(daisy).milk();
}
}

(updated) Olof rightly suggests that cows may not be the clearest way to explain this, so here’s another:


public class LoginControllerTest {

public void shouldRedirectSuccessfulLoginsToTheHomePage() {

// Given an authenticator which allows the user to log in
Authenticator authenticator = mock(Authenticator.class);
stub(authenticator.login("Fred", "P@55word")).toReturn(true);

// When the controller gets Fred's login attempt
LoginController controller = new LoginController(authenticator);
HttpResponse response = controller.attemptLogin("Fred", "P@55word");

// Then the response should redirect us to the home page
assertTrue(response.isRedirect());
assertEquals("/home", response.getRedirectUrl().toString());
}
}

Occasionally I’ll run across something that needs to be explicitly captured in a step as a method; mostly this is sufficient. The audience for the class-level steps is technical, so this works.

You can think of each class as having a stakeholder, or consumer, which is usually another class. There will be something, somewhere in the codebase that uses my Cowhand, or my LoginController (or I probably don’t need to write it yet). The exceptions are GUI classes; their stakeholder is the user.

You’ll notice that I’ve mocked out my collaborators – the CowRepository, or the Authenticator (using Mockito, because it doesn’t require expectations to be set so it allows me to keep the G/W/T flow).

I may not have written the real Cow, CowRepository or Authenticator class yet. This may be the first time I’ve decided that I need one. In that case, by the time I come to code the class, I’ll already have some examples which describe how I expect it to behave.

This entry was posted in bdd. Bookmark the permalink.

9 Responses to Given, when, then and examples for classes

  1. Olof Bjarnason says:

    Liz;

    Could you please translate this to some less-abstract example than milking cows using software..? I just don’t understand what your SUT is all about.

    Maybe something including login-logic or some other more day-to-day software example.

  2. Tore Vestues says:

    Great!

    I guess this post was triggered by my questions on BDD and DDD posted here: http://groups.google.com/group/behaviordrivendevelopment/browse_thread/thread/90e864e69c2e72ef

    This post puts it all together for me. Thank you for taking the time to explain this.

    Now I see that BDD and DDD works nice together.

    – Tore Vestues

  3. Gabriel Schenker says:

    Liz, thanks a lot for all of your very insightful postings here and in the BDD mailing list! I tried to write down your sample for C# and Rhino.Mocks


    [TestFixutre]
    public class CowhandTest {
    [Test]
    public void shouldMilkTheCow() {

    // Given a repository which knows about one cow
    ICowRepository shed = MockRepository.CreateMock();
    Cow daisy = MockRepository.CreateMock();
    shed.Stub(x=>x.getCowByName("Daisy")).Return(daisy);

    // Given a cowhand who knows where the cows are kept
    Cowhand cowhand = new Cowhand(shed);

    // When I ask the cowhand to milk the cow
    cowhand.milkCow("Daisy");

    // Then the cow should have been milked
    daisy.AssertWasCalled(x=>x.milk());
    }
    }

    I try to even re-arrange my test further like this (gives me a clearer separation of concerns)


    [TestFixture]
    public class CowhandTest : SpecificationBase
    {
    protected override void Context() {
    // Given a repository which knows about one cow
    ICowRepository shed = MockRepository.CreateMock();
    Cow daisy = MockRepository.CreateMock();
    shed.Stub(x=>x.getCowByName("Daisy")).Return(daisy);

    // Given a cowhand who knows where the cows are kept
    Cowhand cowhand = new Cowhand(shed);
    }

    protected override void Because() {
    // When I ask the cowhand to milk the cow
    cowhand.milkCow("Daisy");
    }

    [Test]
    public void shouldMilkTheCow() {
    // Then the cow should have been milked
    daisy.AssertWasCalled(x=>x.milk());
    }
    }

  4. Gabriel Schenker says:

    uuups, my angle brackets in the code have been eaten! Should be

    ICowRepository shed = MockRepository.CreateMock<ICowRepository>();
    Cow daisy = MockRepository.CreateMock<Cow>();

    Fixed – I love that I can do that in WordPress! – Liz

  5. Mike says:

    Hi Liz,

    I just wanted to write that test with fluentspec (in c#) if you don’t mind.


    public class CowhandTest : BehaviorOf {

    public void shouldMilkTheCow() {
    var daisy = TestObjectFor();

    Given.Shed.getCowByName("Daisy").Is(daisy);
    When.milkCow("Daisy");
    Then.Should(daisy).milk();
    }
    }

    that was with fluent syntax an having Shed as a property in Cowhand
    keeping it closer to the example with classic syntax would look like ..


    public class CowhandTest {

    public void shouldMilkTheCow() {

    // Given a repository which knows about one cow
    var shed = Create.TestObjectFor();
    var daisy = Create.TestObjectFor();

    Given.That(shed).getCowByName("Daisy").Is(daisy);

    // Given a cowhand who knows where the cows are kept
    var cowhand = new Cowhand(shed);

    // When I ask the cowhand to milk the cow
    cowhand.milkCow("Daisy");

    // Then the cow should have been milked
    Then.Should(daisy).milk();
    }
    }

    cheers
    mike

  6. Mike says:

    opps sorry … the types in the generics TestObjectFor BehaviorOf don’t show in the post 😦

    Fixed, I hope I got them right – Liz

  7. liz says:

    Since I can edit your comments, I’ve thrown the <code> tags in – thank you, these are great!

  8. Phil says:

    In your second example…I think I am missing something. Don’t you need to inject the mock(Authenticator) into the controller? I have not used this framework, so I may be missing something. Thanks.

    Hmm, DI without the I. Fixed! Thanks – Liz

  9. Olof Bjarnason says:

    Liz! Thanks for shedding some more light to my BDD journey! The login example is much easier to understand, I’m not a farmer haha 🙂

    cya

Leave a Reply to Olof Bjarnason Cancel 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 )

Facebook photo

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

Connecting to %s