Fluent Assertions 10 Top Tips

Introduction

The value of writing unit tests is well understood these days and there are some really useful frameworks and tools which developers depend upon.

One such library is Fluent Assertions.  It is an open source library that integrates with several Microsoft platforms such as .NET or .NET Core, and supports several testing frameworks including MS Test, NUnit and XUnit.  The main motivation for its development is to show clear error messages returned by failed tests. Fluent Assertions has many extension methods which can improve the efficiency and readability of unit test code.  The project allows for descriptive outcomes which suits TDD and BDD testing methodologies, but it is useful even if unit tests are written after the main code!

For our backend development, we code mostly in C# and use XUnit as our testing framework. We introduced Fluent Assertions on a project a couple of years ago to help make our assertions cleaner as we particularly liked the concept of Assertion Scopes (more on that later).  Since then, we’ve continued to use Fluent Assertions, but we have used it in a limited way using the same set of features.

However, recently I felt it was time for a knowledge refresh of Fluent Assertions and it has revealed plenty of opportunities for us to improve our unit test code.

This article covers my ten top tips for using Fluent Assertions from this recap.  If you are using this library in your tests, then hopefully there’s a tip or two that helps you out.  This article covers the features that have jumped out at me, but there are many more useful features in the library.

It is assumed that you have a basic knowledge of Fluent Assertions or are actively using it. If you don’t, fear not, you can always skim through the docs later!

 

10 Top Fluent Assertion Tips

So, here are my ten top tips that I will keep in mind from now on when writing unit tests.

At the time of writing Fluent Assertion v5.10.3 was used.

 

1. Use object graph comparison

Some of the early test code we wrote was comparing object graphs and we were writing out property to property comparisons.  As you can imagine, this was quite tedious!

C# unit test code

Fluent Assertions has a really useful extension method BeEquivalentTo().   This allows object graph comparison and therefore removes the need to list all properties for comparison.  This reduces the time required to write the test code and there is less of it to read and maintain.

Use of BeEquivalentTo() method

BeEquivalentTo() is very powerful and has plenty of options.  Among its features, you can select properties and/or fields to include or exclude, specify collection order, and it has a diagnostics mode to help debug deep into object graphs.

 

2. Use Date formatting extension methods

There are a set of date formatting extension methods which allow for dates and times to be written more expressively.  This approach provides clarity which is useful for non-developers to understand the test code.

Date formatting extension method usage

 

3. Use DateTime and TimeSpan assertions

There are lots of useful assertions for dates and times and using them helps to make the code more readable.  Use these extensions to replace the traditional code comparison operators. 

One other point to mention, a date can be checked that it falls within a certain timeframe.

Date extension method

 

4. Use Collection extension methods

Beyond the typical collection assertion methods you would expect to find, such as checking the count, there are some powerful methods to perform assertions on collections and the items they contain.  These include asserting the order of the items, checking for uniqueness and whether a collection is a subset of another collection.

Collection extension methods

Other powerful methods include Contain and ContainSingle, these help validate that at least one or exactly one item in the collection meets a criteria.

Finally, SatisfyRespectively is a method which allows you to perform complex assertions on each item in a collection.

 

5. Use Which

The Which extension allows for another assertion to be chained onto a previous assertion that identifies a single item in a collection.

Use of Which() extension method

 

6. Use Exception Assertions

In our code we are using the exception assertions for top-level exception type checking.  However, there is more that can be done! Using WithMessage allows us to check the message content is as expected.  Also, it is possible to check the inner exception and the individual properties of the exception.

 

7. Use Perform Assembly Assertions

In many of the systems we develop we use a layered architecture, specifically the Onion Architecture. This architecture states that code can only reference immediate inner layers. Fluent Assertions provides a pair of useful assertions to check that this rule is enforced at the assembly level.

Use of Reference() and NotReference() extension methods

 

8. Improve Should().BeTrue() code

Ok, so this is actually a tip from the Fluent Assertions documentation itself!  If the code is not evaluating a Boolean directly, then it is likely that Should().BeTrue() assertions can be written using a more expressive assertion syntax.  This will improve readability and the error message displayed. There are myriad examples in the documentation to check out.

 

9. Use AssertionScope

This is something that we already use and it is quite a fundamental feature, but it is worthwhile mentioning.  By using the using (new AssertionScope()) { } code block, all assertions are evaluated and if the test fails, the error will include all messages from multiple failed assertions.

 

10. Other points

Finally, a couple of other things were noticed when reading through the docs.  Neither of these features we currently need to use, but they are now kept in mind:

  • Can perform execution time assertions to check code performance.
  • Can perform XML assertions on LINQ-to-XML classes.

 

Conclusion

We like Fluent Assertions for the benefits of clear error messages, more readable test code and that fewer lines of code are needed for our tests.  We are pleased to have refreshed our knowledge in this area and we can improve our future tests as well as refactor older ones.

This exercise taught us an important lesson in general.  The world of software development is ever-changing and it pays dividends to keep up to date with existing tools.

Refreshing your knowledge of the libraries, tools and frameworks you use will provide valuable benefits to you, your code and those you work for.

 

Find out more about our custom software development services or get in touch today for a no obligation chat about your next software development project.

Jonathan Dodd, Co-Founder of Innovensa

Jonathan Dodd

Jonathan Dodd is a co-founder of Innovensa Ltd.

Back to top