Click here to Skip to main content
15,886,518 members
Articles / Programming Languages / C#

Behavior-Driven Development with NBehave

Rate me:
Please Sign up or sign in to vote.
4.97/5 (35 votes)
13 Jan 2009CPOL11 min read 88.6K   376   81  
A BDD tutorial using NBehave and MbUnit.
/* Copyright (C) Dmitri Nesteruk */

using System;

namespace ConsoleApplication1
{
  using NBehave.Narrator.Framework;
  using NBehave.Spec.MbUnit;
  using MbUnit.Framework;

  using That = MbUnit.Framework.TestAttribute;
  using Describe = MbUnit.Framework.CategoryAttribute;
  using For = MbUnit.Framework.CategoryAttribute;
  using Wrote = MbUnit.Framework.DescriptionAttribute;
  using Should = MbUnit.Framework.DescriptionAttribute;
  using Full = MbUnit.Framework.MultipleAssertsAttribute;

  [
    Author("Dmitri", "dmitrinesteruk@gmail.com"),
    Wrote("Account operation tests"),
    TestsOn(typeof(Account)),
    For("Banking system")
  ]
  public class AccountTest : SpecBase
  {
    public Account account;
    public Account account2;

    [SetUp]
    public void Initialize_before_each_test()
    {
      account = new Account();
      account2 = new Account { Balance = 100 };
    }

    [Full, Story, That, Should("Increase account balance when money is deposited")]
    public void Deposit_should_increase_account_balance()
    {
      Story story = new Story("Deposit");
      story.AsA("User")
        .IWant("The bank account balance to increase by the amount deposited")
        .SoThat("I can deposit money");

      story.WithScenario("Money deposit")
        .Given("My bank account is empty", () => { account.Balance = 0; })
        .When("I deposit 100 units", () => account.Deposit(100))
        .Then("The account balance should be 100", () => account.Balance.ShouldEqual(100));

      story.WithScenario("Negative amount deposit")
        .Given("My bank account is empty", () => { account.Balance = 0; })
        .When("I try to deposit a negative amount", () => { })
        .Then("I get an exception",
              () => typeof(Exception).ShouldBeThrownBy(() => account.Deposit(-100)))
        .And("My bank account balance is unchanged",
             () => account.Balance.ShouldEqual(0));
    }

    [Story, That, Should("Decrease account balance when money is withdrawn")]
    public void Withdrawal_should_decrease_account_balance()
    {
      Story story = new Story("Withdrawal");
      story.AsA("User")
        .IWant("To be able to withdraw money if I have it")
        .SoThat("I can buy things");

      story.WithScenario("Withdrawal with empty bank account")
        .Given("My bank is empty", () => { account.Balance = 0; })
        .When("I try to withdraw money", () => {})
        .Then("I get an exception", () =>
              typeof(Exception).ShouldBeThrownBy(() => account.Withdraw(100)))
        .And("I still have an empty bank account", () => account.Balance.ShouldEqual(0));

      story.WithScenario("Withdrawal with sufficient balance")
        .Given("I've got 100 dollars in my bank account", () => { account.Balance = 100; })
        .When("I try to withdraw 50 dollars", () => account.Withdraw(50))
        .Then("I have 50 dollars left in the account",
              () => account.Balance.ShouldEqual(50));
    }

    [Story, That, Should("Transfer money from one account to another")]
    public void Transfer_should_move_money_from_one_account_to_another()
    {
      Story story = new Story("Tranfer");
      story.AsA("User").IWant("The transfer feature to be atomic")
        .SoThat("My money isn't lost");

      story.WithScenario("Valid transfer")
        .Given("I have 100 dollars", () => { account.Balance = 100; })
        .And("You have 100 dollars", () => { account2.Balance = 100; })
        .When("I give you 50 dollars",
              () => Assert.DoesNotThrow(() => Account.Transfer(account, account2, 50)))
        .Then("I have 50 dollars left", () => account.Balance.ShouldEqual(50))
        .And("You have 150 dollars", () => account2.Balance.ShouldEqual(150));
    }
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder ActiveMesa
United Kingdom United Kingdom
I work primarily with the .NET technology stack, and specialize in accelerated code production via code generation (static or dynamic), aspect-oriented programming, MDA, domain-specific languages and anything else that gets products out the door faster. My languages of choice are C# and C++, though I'm open to suggestions.

Comments and Discussions