Pimp Up Your Unit Test Assertions

In this post I’m going to show you how you can write your unit test assertions to read more fluently and allow you to be more productive.

The Plain Jane Unit Test Assertion

[Test]
public void The_Plain_Jane_Assertion()
{
    const string firstString = "Hello World";
    const string secondString = "Hello World";

    const int smallNumber = 1;
    const int bigNumber = 500;

    // Are Equal
    Assert.AreEqual(firstString, secondString);

    // Greater Than
    Assert.Greater(bigNumber,smallNumber);

    // Less Than
    Assert.Less(smallNumber,bigNumber);
}

This is what most developers will start off using. No problem with the equals assertion it easy enough to read and use.

However when using the greater or less than assertions, it’s not clear if the first argument should be the lower or the higher value as shown in the screen shot below.

NUnit Assert Confusion

This distraction can easily stop your flow.

The More Fluent NUnit Test Assertion

[Test]
public void The_More_Fluent_Nunit_Assertion()
{
    const string firstString = "Hello World";
    const string secondString = "Hello World";

    const int smallNumber = 1;
    const int bigNumber = 500;

    // Are Equal
    Assert.That(firstString, Is.EqualTo(secondString));

    // Greater Than
    Assert.That(bigNumber, Is.GreaterThan(smallNumber));

    // Less Than
    Assert.That(smallNumber, Is.LessThan(bigNumber));
}

The unit test assertions read a lot more fluently, we no longer have to be concerned about the order of arguments.

If you don’t want to use another third party library, this is for you.

The Super Fluent NBehave Spec Assertion

[Test]
public void The_Super_Fluent_NBehave_Spec_Assertion()
{
    const string firstString = "Hello World";
    const string secondString = "Hello World";

    const int smallNumber = 1;
    const int bigNumber = 500;

    // Are Equal
    firstString.ShouldEqual(secondString);

    // Greater Than
    bigNumber.ShouldBeGreaterThan(smallNumber);

    // Less Than
    smallNumber.ShouldBeLessThan(bigNumber);
}

This example uses the NBehave Spec Framework which you can download from the NBehave site. In addition to being very easy to understand, the use of extension methods means there is a lot less noise.

Some developers will be concerned by losing the word ‘Assert’ in the line that does the assertion. If you arrange your tests using the Arrange, Act, Assert pattern this should not be a problem. See the example below.

[Test]
public void The_NBehave_Spec_Assertion_Using_Arrange_Act_Assert()
{
    // Arrange
    const int inputValue = 1;

    // Act
    var result = inputValue + 1;

    // Assert
    result.ShouldBeGreaterThan(inputValue);
}

Comments

  • http://www.dennisdoomen.net Dennis Doomen

    Jag, in terms of intention revealing unit tests, you may like http://fluentassertions.codeplex.com. With it you can do stuff like

    “ABCDEFGHI”.Should().StartWith(“AB”).And.EndWith(“HI”).And.Contain(“EF”).And.HaveLength(9);

    new[] { 1, 2, 3 }.Should().HaveCount(4, “because we thought we put three items in the
    collection”))

    dtoCollection.Should().Contain(dto => dto.Id != null);

    collection.Should().HaveCount(c => c >= 3);

    dto.ShouldHave().AllPropertiesBut(d => d.Id).EqualTo(customer);

    dt1.Should().BeWithin(TimeSpan.FromHours(50)).Before(dt2);

    Action action = () => recipe.AddIngredient(“Milk”, 100, Unit.Spoon);
    action
    .ShouldThrow()
    .WithMessage(“Cannot change the unit of an existing ingredient”)
    .And.Violations.Should().Contain(BusinessRule.CannotChangeIngredientQuanity