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
}
[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
}
[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.