In this post, we will see what “Fluent Assertions” is and how we can use it in our projects.
But first of all, what is “Fluent Assertions”?
Fluent Assertions is a popular library for writing more expressive and readable unit tests in C#.
It provides a fluent, natural language syntax for asserting the behaviour of our code.
For all information, we can consult the official web site.
We start to create a xUnit Test project and then, we add the Fluent Assertions NuGet package to the project, using the command:
Install-Package FluentAssertions
Now, we are ready to use “Fluent Assertion” in our tests but, before to start, I want to highlight that we will create very easy tests because, the goal of this post is not the tests creations but, how to use “Fluent Assertion”.
BASIC ASSERTIONS:
using FluentAssertions;
using Xunit;
namespace FluentAssertionsTest
{
public class Calculator
{
public int Add(int val1, int val2)
{
return val1 + val2;
}
}
public class TestFluentAssertions
{
// Basic Assertions
[Fact]
public void Add_Should_Return_Correct_Sum()
{
// Arrange
var calculator = new Calculator();
// Act
int result = calculator.Add(2, 3);
// Assert
// Fluent assertion: Check if result is 5
result.Should().Be(5);
}
}
}
If we run the application, the following will be the result:
CHAINING ASSERTIONS:
using FluentAssertions;
using Xunit;
namespace FluentAssertionsTest
{
public class Calculator
{
public int Add(int val1, int val2)
{
return val1 + val2;
}
public double Divide(int val1, int val2)
{
return val1 / val2;
}
}
public class TestFluentAssertions
{
// Chaining Assertions
[Fact]
public void Divide_Should_Return_Correct_Result()
{
// Arrange
var calculator = new Calculator();
// Act
double result = calculator.Divide(10, 2);
// Assert
result.Should()
.Be(5) // Check if result is 5
.And
.BeGreaterThan(4) // Check if result is greater than 4
.And
.BeLessOrEqualTo(6); // Check if result is less than or equal to 6
}
}
}
If we run the application, the following will be the result:
COLLECTION ASSERTIONS:
using FluentAssertions;
using System.Collections.Generic;
using Xunit;
namespace FluentAssertionsTest
{
public class TestFluentAssertions
{
// Collection Assertions
[Fact]
public void Check_List_Contents()
{
// Arrange
var numbers = new List<int> { 1, 2, 3, 4, 5 };
// Assert
numbers.Should()
.Contain(3) // Check if the list contains 3
.And
.HaveCount(5) // Check if the list has 5 elements
.And
.NotContain(6) // Check if the list does not contain 6
.And
.OnlyHaveUniqueItems(); // Check if all items are unique in the list
}
}
}
If we run the application, the following will be the result:
STRING ASSERTIONS:
using FluentAssertions;
using System.Collections.Generic;
using Xunit;
namespace FluentAssertionsTest
{
public class TestFluentAssertions
{
// String Assertions
[Fact]
public void StringAssertions()
{
// Arrange
string greeting = "Hello, World";
// Assert
greeting.Should()
.StartWith("Hello") // Check if the string starts with "Hello"
.And
.EndWith("World") // Check if the string ends with "World"
.And
.Contain("o,") // Check if the string contains "o,"
.And
.HaveLength(12); // Check if the string has a length of 12
}
}
}
If we run the application, the following will be the result:
OBJECT EQUALITY:
using FluentAssertions;
using Xunit;
namespace FluentAssertionsTest
{
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestFluentAssertions
{
// Object Equality
[Fact]
public void ObjectEquality()
{
// Arrange
var person1 = new Person { FirstName = "John", LastName = "Doe" };
var person2 = new Person { FirstName = "John", LastName = "Doe" };
// Assert
person1.Should().BeEquivalentTo(person2); // Check if properties of objects are equal
}
}
}
If we run the application, the following will be the result:
EXCEPTION ASSERTIONS:
using FluentAssertions;
using System;
using Xunit;
namespace FluentAssertionsTest
{
public class Calculator
{
public int Add(int val1, int val2)
{
return val1 + val2;
}
public double Divide(int val1, int val2)
{
return val1 / val2;
}
}
public class TestFluentAssertions
{
// Exception Assertions
[Fact]
public void ExceptionAssertions()
{
// Arrange
var calculator = new Calculator();
// Act & Assert
Action act = () => calculator.Divide(10, 0);
// Assert that an exception of type DivideByZeroException is thrown
// with the specified error message.
act.Should()
.Throw<DivideByZeroException>()
.WithMessage("Attempted to divide by zero.");
}
}
}
If we run the application, the following will be the result:
NULLABLE TYPE ASSERTIONS:
using FluentAssertions;
using Xunit;
namespace FluentAssertionsTest
{
public class TestFluentAssertions
{
// Nullable Type Assertions
[Fact]
public void NullableTypeAssertions()
{
// Arrange
int? nullableValue = null;
// Assert that the nullableValue does not have a value (is null)
nullableValue.Should().NotHaveValue();
}
}
}
If we run the application, the following will be the result:
DATE TIME ASSERTIONS:
using FluentAssertions;
using System;
using Xunit;
namespace FluentAssertionsTest
{
public class TestFluentAssertions
{
// DateTime Assertions
[Fact]
public void DateTimeAssertions()
{
// Arrange
DateTime now = DateTime.Now;
DateTime later = now.AddMinutes(5);
// Assert that 'later' is after 'now' and that it is within 6 minutes
// after 'now'.
later.Should().BeAfter(now)
.And
.BeWithin(TimeSpan.FromMinutes(6)).After(now);
}
}
}
If we run the application, the following will be the result:
“Fluent Assertions” is a valuable tool for writing expressive and readable unit tests in C#.
Its natural language syntax makes it easier to convey the intent of our tests, and its extensive set of assertions allows us to cover a wide range of scenarios.
By adopting “Fluent Assertions”, we can enhance the quality of our unit tests and make our codebase more robust.