Search code examples
c#unit-testingmstestbddmspec

How do I write context/specification style unit tests with an MSTest/xUnit framework?


I have been using MSpec to write my unit tests and really prefer the BDD style, I think it's a lot more readable. I'm now using Silverlight which MSpec doesn't support so I'm having to use MSTest but would still like to maintain a BDD style so am trying to work out a way to do this.

Just to explain what I'm trying to acheive, here's how I'd write an MSpec test

[Subject(typeof(Calculator))]    
public class when_I_add_two_numbers : with_calculator
{
  Establish context = () => this.Calculator = new Calculator();
  Because I_add_2_and_4 = () => this.Calculator.Add(2).Add(4);
  It should_display_6 = () => this.Calculator.Result.ShouldEqual(6);
}

public class with_calculator
{
  protected static Calculator;
}

So with MSTest I would try to write the test like this (although you can see it won't work because I've put in 2 TestInitialize attributes, but you get what I'm trying to do..)

[TestClass]
public class when_I_add_two_numbers : with_calculator
{
   [TestInitialize]
   public void GivenIHaveACalculator()
   {
      this.Calculator = new Calculator();
   }

   [TestInitialize]
   public void WhenIAdd2And4()
   {
      this.Calculator.Add(2).Add(4);
   }

   [TestMethod]
   public void ThenItShouldDisplay6()
   {
      this.Calculator.Result.ShouldEqual(6);
   }
}

public class with_calculator
{
  protected Calculator Calculator {get;set;}
}

Can anyone come up with some more elegant suggestions to write tests in this way with MSTest?


Solution

  • What you think about this one:

    [TestClass]
    public class when_i_add_two_numbers : with_calculator
    {
        public override void When()
        {
            this.calc.Add(2, 4);
        }
    
        [TestMethod]
        public void ThenItShouldDisplay6()
        {
            Assert.AreEqual(6, this.calc.Result);
        }
    
        [TestMethod]
        public void ThenTheCalculatorShouldNotBeNull()
        {
            Assert.IsNotNull(this.calc);
        }
    }
    
    public abstract class with_calculator : SpecificationContext
    {
        protected Calculator calc;
    
        public override void Given()
        {
            this.calc = new Calculator();
        }
    }
    
    public abstract class SpecificationContext
    {
        [TestInitialize]
        public void Init()
        {
            this.Given();
            this.When();
        }
    
        public virtual void Given(){}
        public virtual void When(){}
    }
    
    public class Calculator
    {
        public int Result { get; private set; }
        public void Add(int p, int p_2)
        {
            this.Result = p + p_2;
        }
    }