Fluent Assertions in C# Unit Tests
Introduction
In this blog post, I’ll introduce you to Fluent Assertions, a collection of .NET extension methods designed to replace standard assertions within unit tests.
While these extension methods aren’t essential, they simplify writing tests and, more importantly, make them much easier to read and understand.
Getting Started
The first step is to install the Fluent Assertions package, this can be done through the command line or using NuGet Package Manager:
- Command line
Use either of the following commands:Install-Package FluentAssertions
ordotnet add package FluentAssertions
- NuGet Package Manager
Use the package manager window available within your IDE
After installing the package, the followingusing
statement should be added to each test class:
using FluentAssertions;
Usage
Detailed below are some basic examples of commonly used extension methods available within the library:
- Verifying integer types using the extension method
Should().Be()
[Fact]
public void Test_IntegerInput_MatchesExpectedResult()
{
const int actual = 100;
const int expected = 100;
actual.Should().Be(expected);
}
- Verifying string types using the extension method
Should().Be()
[Fact]
public void Test_StringInput_MatchesExpectedResult()
{
const string actual = "This is a test string";
const string expected = "This is a test string";
actual.Should().Be(expected);
}
- Verifying string types using the extension method
Should().Contain()
[Fact]
public void Test_StringInput_ContainsExpectedResult()
{
const string actual = "This is a test string";
const string expected = "test";
actual.Should().Contain(expected);
}
- Verifying boolean types using the extension methods
Should().BeTrue()
andShould().Be()
[Fact]
public void Test_BooleanInput_MatchesExpectedResult()
{
const bool actual = true;
const bool expected = true;
actual.Should().BeTrue();
actual.Should().Be(expected);
}
- Verifying array types using the extension methods
Should().BeEquivalentTo()
andShould().HaveCount()
[Fact]
public void Test_StringArrayInput_ContainsExpectedResult()
{
IEnumerable<string> actual = new[] { "Alice", "Bob", "Charles", "David" };
IEnumerable<string> expected = new[] { "Alice", "Bob", "Charles", "David" };
actual.Should().BeEquivalentTo(expected);
actual.Should().HaveCount(4);
}
- Verifying a thrown exception (in this case ArgumentNullException) using the extension method
Should().Throw<>()
[Fact]
public void Test_ThrowsException_WhenArgumentIsNull()
{
Action action = () => new TestService(null);
action.Should().Throw<ArgumentNullException>();
}
- Verifying a thrown exception (in this case ArgumentNullException) with a specific message using the extension method
Should().Throw<>().WithMessage()
[Fact]
public void Test_ThrowsExceptionWithMessage_WhenArgumentIsNull()
{
Action action = () => new TestService(null);
action.Should().Throw<ArgumentNullException>()
.WithMessage("Parameter is NULL");
}
- Verifying integer types using the extension method
Should().Be().
This example illustrates a failing test due to a mismatch between the actual and expected values. The error message generated from this failed test is shown, clearly indicating the reason for the failure.
[Fact]
public void Test_IntegerInput_MatchesExpectedResult()
{
const int actual = 100;
const int expected = 90;
actual.Should().Be(expected);
}
- Finally, here are some common extensions that can be used to check for the null and empty collections.
[Fact]
public void Test_StringArrayInput_IsNullOrEmpty()
{
IEnumerable<string> actualIsNull = null;
IEnumerable<string> actualIsEmpty = Array.Empty<string>();
actualIsNull.Should().BeNull();
actualIsNull.Should().BeNullOrEmpty();
actualIsEmpty.Should().BeEmpty();
actualIsEmpty.Should().BeNullOrEmpty();
}
[Fact]
public void Test_StringArrayInput_IsNotNullOrEmpty()
{
IEnumerable<string> actual = new[] { "Alice", "Bob", "Charles", "David" };
actual.Should().NotBeNull();
actual.Should().NotBeEmpty();
actual.Should().NotBeNullOrEmpty();
}
Reference Material
The most comprehensive documentation can be found within the official Fluent Assertions website and GitHub Repo.
Conclusion
As you can see, the samples I provided are as simple as possible with most producing a test that will pass. They are designed to provide an introduction and illustration of the basics of the Fluent Assertions library. There are many more extensions available, all of which themselves are highly extendable with additional chaining available to test for multiple conditions.
I hope you found this blog helpful and consider using Fluent Validations when next writing unit tests.