Should & Substitute–two new great friends

· November 5, 2010

Recently I’ve stumbled upon two great framework that greatly enhanced my test code.

Should I? Yes – you should

First up is Should – which is a assertion framework that makes your assertions much more readable and easier to write. Here’s some code that shows off it’s capabilities: object obj = null;

    obj = new object();
    obj.Should().Be.OfType(typeof(object));
    obj.Should().Equal(obj);
    obj.Should().Not.Be.Null();
    obj.Should().Not.Be.SameAs(new object());
    obj.Should().Not.Be.OfType<string>();
    obj.Should().Not.Equal("foo");
   "This String".Should().Contain("This");
    "This String".Should().Not.Be.Empty();
    "This String".Should().Not.Contain("foobar");
   var list = new List<object>();
    list.Should().Count.Zero();
    list.Should().Not.Contain.Item(new object());
   var item = new object();
    list.Add(item);
    list.Should().Not.Be.Empty();
    list.Should().Contain.Item(item);

One really nice feature is that the framework isn’t tied to any testing framework but works nicely with any test framework.

Get me a substitute! Now

The other framework is NSubstitute which is a mocking framework. I first got hooked when I read their intro:

Mock, stub, fake, spy, test double? Strict or loose? Nah, just substitute for the type you need!

I’m probably the only one (NOT!) who mess mock, stubs and fakes up except from just after I read a book on the subject. And really – who cares? I just want something to replace the real stuff for a while – let’s call it a substitute.

The syntax is also super-clean and easy going. Here’s the example from the NSubstitute site: //Create:

//Set a return value:
calculator.Add(1, 2).Returns(3);
Assert.AreEqual(3, calculator.Add(1, 2));    //Check received calls:
calculator.Received().Add(1, Arg.Any<int>());
calculator.DidNotReceive().Add(2, 2);

Come together. Right now

But the true power, I think, you get when combining these two together. Here’s an example from I did to show SpecFlow that uses both Should and NSubsitute: [Given(@”the following features in the database:”)] public void GivenTheFollowingFeaturesInTheDatabase(Table table) { var features = table.CreateSet().ToList(); var dbWrapperSubsitute = Substitute.For();

}

[When(@"I navigate to the homepage")]
public void WhenINavigateToTheHomepage()
{
    var featureDBWrapper = ScenarioContext.Current.Get<IFeatureDBWrapper>(DBWRAPPER_KEY);
    var controller = new HomeController(featureDBWrapper);
   var indexView = controller.Index() as ViewResult;
   indexView.Should().Not.Be.Null();
    indexView.ViewData.Model.Should().Not.Be.Null();
    var features = (IList<Feature>)indexView.ViewData.Model;
    features.Should().Not.Be.Null();
   featureDBWrapper.Received().AllNotDone();
   ScenarioContext.Current.Set(features, FEATURES_IN_VIEW_KEY);

[Then(@"I should see a view with the following features:")]
public void ThenIShouldSeeAViewWithTheFollowingFeatures(Table table)
{
    var features = ScenarioContext.Current.Get<IList<Feature>>(FEATURES_IN_VIEW_KEY);
   var expectedFeatures = table.CreateSet<Feature>();
   foreach (var expectedFeature in expectedFeatures)
    {
        features.Should().Contain.Any( f => f.Name ==  expectedFeature.Name);
        features.Should().Contain.Any( f => f.AssignedTo ==  expectedFeature.AssignedTo);
        features.Should().Contain.Any( f => f.HoursWorked ==  expectedFeature.HoursWorked);
        features.Should().Contain.Any( f => f.Status ==  expectedFeature.Status);
        features.Should().Contain.Any( f => f.Size ==  expectedFeature.Size);
    }
}

You can find the whole solution here.

Recently I’ve stumbled upon two great framework that greatly enhanced my test code.

Should I? Yes – you should

First up is Should – which is a assertion framework that makes your assertions much more readable and easier to write. Here’s some code that shows off it’s capabilities: object obj = null;

    obj = new object();
    obj.Should().Be.OfType(typeof(object));
    obj.Should().Equal(obj);
    obj.Should().Not.Be.Null();
    obj.Should().Not.Be.SameAs(new object());
    obj.Should().Not.Be.OfType<string>();
    obj.Should().Not.Equal("foo");
   "This String".Should().Contain("This");
    "This String".Should().Not.Be.Empty();
    "This String".Should().Not.Contain("foobar");
   var list = new List<object>();
    list.Should().Count.Zero();
    list.Should().Not.Contain.Item(new object());
   var item = new object();
    list.Add(item);
    list.Should().Not.Be.Empty();
    list.Should().Contain.Item(item);

One really nice feature is that the framework isn’t tied to any testing framework but works nicely with any test framework.

Get me a substitute! Now

The other framework is NSubstitute which is a mocking framework. I first got hooked when I read their intro:

Mock, stub, fake, spy, test double? Strict or loose? Nah, just substitute for the type you need!

I’m probably the only one (NOT!) who mess mock, stubs and fakes up except from just after I read a book on the subject. And really – who cares? I just want something to replace the real stuff for a while – let’s call it a substitute.

The syntax is also super-clean and easy going. Here’s the example from the NSubstitute site: //Create:

//Set a return value:
calculator.Add(1, 2).Returns(3);
Assert.AreEqual(3, calculator.Add(1, 2));    //Check received calls:
calculator.Received().Add(1, Arg.Any<int>());
calculator.DidNotReceive().Add(2, 2);

Come together. Right now

But the true power, I think, you get when combining these two together. Here’s an example from I did to show SpecFlow that uses both Should and NSubsitute: [Given(@”the following features in the database:”)] public void GivenTheFollowingFeaturesInTheDatabase(Table table) { var features = table.CreateSet().ToList(); var dbWrapperSubsitute = Substitute.For();

}

[When(@"I navigate to the homepage")]
public void WhenINavigateToTheHomepage()
{
    var featureDBWrapper = ScenarioContext.Current.Get<IFeatureDBWrapper>(DBWRAPPER_KEY);
    var controller = new HomeController(featureDBWrapper);
   var indexView = controller.Index() as ViewResult;
   indexView.Should().Not.Be.Null();
    indexView.ViewData.Model.Should().Not.Be.Null();
    var features = (IList<Feature>)indexView.ViewData.Model;
    features.Should().Not.Be.Null();
   featureDBWrapper.Received().AllNotDone();
   ScenarioContext.Current.Set(features, FEATURES_IN_VIEW_KEY);

[Then(@"I should see a view with the following features:")]
public void ThenIShouldSeeAViewWithTheFollowingFeatures(Table table)
{
    var features = ScenarioContext.Current.Get<IList<Feature>>(FEATURES_IN_VIEW_KEY);
   var expectedFeatures = table.CreateSet<Feature>();
   foreach (var expectedFeature in expectedFeatures)
    {
        features.Should().Contain.Any( f => f.Name ==  expectedFeature.Name);
        features.Should().Contain.Any( f => f.AssignedTo ==  expectedFeature.AssignedTo);
        features.Should().Contain.Any( f => f.HoursWorked ==  expectedFeature.HoursWorked);
        features.Should().Contain.Any( f => f.Status ==  expectedFeature.Status);
        features.Should().Contain.Any( f => f.Size ==  expectedFeature.Size);
    }
}

You can find the whole solution here.

Twitter, Facebook