Sparky's Tool Tips: Fluent Assertions
Tags: csharp, dotnet, testing, productivity
Published: 2021-07-11 14:20:53

I like writing unit tests more than the average developer (not saying much, I realize - Testing is something many devs... de-*test* 🥁).

I really appreciate tools that make it easier and more fun to write tests (in fact, [I've written some myself](https://dev.to/sparky/sparkytesthelpers-1n0h)), and [Fluent Assertions](https://fluentassertions.com/) is one of my favorites.

![Fluent Assertions logo](https://fluentassertions.com/assets/images/fluent_assertions_large_horizontal.svg)

The [Microsoft.VisualStudio.TestTools.UnitTesting](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.testtools.unittesting) **Assert**, **StringAssert** and **CollectionAssert** classes are... *OK*, I guess. (It's been a while since I used NUnit and I've never used xUnit, so I don't know about the built-in asserts in those frameworks.)

Fluent Assertions is a set of .NET extension methods that allow you to specify the expected outcome of a TDD or BDD-style unit test with a sentence-like syntax. For example, the "MSTest" syntax:

```csharp
Assert.AreEqual(31, daysInJune);
```
...can be fluently expressed as:

```csharp
using FluentAssertions;
. . .
daysInJune.Should().Be(31);
```
"Using" the "FluentAssertions" namespace enables a ton of useful "Should()" extension methods for:

#### strings:
- Be(*expected*)
- BeNull()
- BeEmpty()
- StartWith(*expected*)
- EndWith(*expected*)
- HaveLength(*expected*)
- Contain(*expected*)
- ...

#### numbers:
- Be(*expected*)
- BeGreatorOrEqualTo(*expected*)
- BeLessOrEqualTo(*expected*)
- BeInRange(*minimum*, *maximum*)
- BePositive()
- ...

#### DateTime:
- Be(1.March(2022).At(22, 15))
- BeOnOrAfter(1.March(2010))
- HaveDay(1)
- HaveMonth(3)
- HaveYear(2010)
- HaveHour(22)
- BeLessThan(10.Minutes()).Before(*otherDatetime*)
- ...

#### collections:
- HaveCount(*expected*)
- HaveSameCount(*otherCollection*)
- Contain(*expected*)
- NotContain(*expected*)
- OnlyContain(x => x.**predicate**)
- ...

These are just a few examples. There are dozens more methods for these and many other types.

###*And*... assertions are chainable!

```csharp
string stateName = "OHIO";
stateName.Should().StartWith("O").And.EndWith("O").And.Contain("HI");
```

##Exceptions
I don't like the MS Test ``[ExpectedException(type)]`` attribute. Among other shortcomings, it doesn't let you test the exception message.

With Fluent Assertions, exception testing looks like this:

```csharp
subject.Invoking(x => x.Foo("Hello"))
    .Should().Throw<InvalidOperationException>()
    .WithMessage("Hello is not allowed at this moment");
```
...or with "arrange / act / assert" syntax:
```csharp
Action action = () => x.Foo("Hello");

action
    .Should().Throw<InvalidOperationException>()
    .WithMessage("Hello is not allowed at this moment");
```

##Extensibility
Fluent Assertions is nicely set up to allow you to write your own "Should" extension methods.

There are [many NuGet packages](https://www.nuget.org/packages?q=fluent+assertions) containing additional extension methods, including my own [SparkyTestHelpers.Moq.Fluent](https://www.nuget.org/packages/SparkyTestHelpers.Moq.Fluent/).

##But wait, there's more!

Fluent Assertions doesn't just give you better syntax for writing assertions - it gives you much better messages when an assertion fails, for example:

With Assert.AreEqual:
```csharp
string correctNameSpelling = "Bryan";
Assert.AreEqual("Brian", correctNameSpelling);
```
...the failure message is:
```
Assert.AreEqual failed. Expected:<Brian>. Actual:<Bryan>.
```

With Fluent Assertions:
```csharp
string correctNameSpelling = "Bryan";
correctNameSpelling.Should().Be("Brian");
```
..the failure message is: 
```
Expected correctNameSpelling to be "Brian", but "Bryan" differs near "yan" (index 2).
```
The "differs near" and index are a bit of overkill for strings this short, but pretty handy for long strings!

(BTW, this is not a trivial example. correctNameSpelling SHOULD BE "Brian" and if your parents named you "Bryan", you should call them and complain.😏)
***
I like Fluent Assertions *a lot*, and if you're writing .NET unit tests, I think you **.*Should*()** give it a try!