I recently discovered a very cool project on NuGet – FluentAssertions. This is a really funky little library that vastly improves assertions in your unit tests, whether you are using NUnit or MsTest. I’ve been using it for a few weeks now and thought I would share some of the cool things you can do with this framework. I’ll start with the simple stuff and over the next few weeks show some of the assertions you can make on dates and collections, then exceptions and events and creating your own assertions and using this to map unit tests more closely to acceptance criteria. Some of this will duplicate the documentation on codeplex, but I’ll go into more detail about how to use the techniques in practice.

Firstly, go and NuGet FluentAssertions into one of your test projects. Next go and find some string assertion, which will probably look something like this (I’m using MsTest):

Assert.AreEqual("123,456,789", result);

You can replace this with the following FluentAssertion:

result.Should().Be("123,456,789");

OK, so this already reads much more nicely, which is great, but the reporting of a failed assertion is also improved. If result was the wrong value with the AreEqual assertion you would get the following:

Assert.AreEqual failed. Expected:<123,456,789>. Actual:<123,458,789>.

This is alright, but it could be tricky to notice the 8 which should be a 6. Compare that to the FluentAssertion’s reporting:

Expected string to be
"123,456,789", but
"123,458,789" differs near "8,7" (index 6).

 

Not only have the expected and actual values been lined up vertically to aid scanning, but the message even highlights the point in the string the values differ.

You’ll notice if you type Should() and look at the code completion list that you get a lot of options. You could use StartWith or EndWith, or even do a wildcard match using Match. You can also chain your expectations together using the And property, so instead of:

result.Should().NotBeNullOrEmpty();
result.Should().NotMatch("*,");
result.Should().NotMatch(",*");

You can write:

result.Should().NotBeNullOrEmpty()
  .And.NotMatch("*,")
  .And.NotMatch(",*");

 

This quickly makes your unit tests much more readable.

You can ignore casing easily, so instead of

Assert.AreEqual("hello", result.ToLower());

You can use

result.Should().BeEquivalentTo("hello");

This is just the options available for strings. There are all the options you would expect for numbers too:

result.Should().BeGreaterOrEqualTo(5);
result.Should().BeInRange(2, 27);
result.Should().BeNegative();

The cool thing about these expectations is that they will work for any object implementing the IComparable interface too!

Finally, each expectation can take a reason string too, which will be printed out along with an expectation error:

result.Should().Match("JM*", "because result should be a valid UK insurance number");
Expected string to match "JM*" because result should be a valid UK insurance number,
but "INVALID" does not match.

This is not only helpful when the test fails, but when looking at the test code it reads much more like a set of acceptance criteria, so the intent of your test is more obvious.

I hope this will encourage a few of you to use this great library – next time I’ll go through the things you can do with collections, dates and times, and then get into creating your own custom expectations.