In this article I wanted to tell you about a library that can help you improve your unit testing in C#. It's the FluentAssertions library, which provides us with a lot of extension methods that allow us to write better, so-called fluent assertions.
FluentAssertions Library
First, please familiarize yourself with the ProductService class.
public class ProductService
{
private readonly IProductValidator _productValidator;
public ProductService(IProductValidator productValidator)
{
_productValidator = productValidator;
Products = new List<Product>();
}
public IList<Product> Products { get; set; }
public void Add(Product product)
{
if (_productValidator.IsAvailable(product))
Products.Add(product);
}
}
We are mainly interested in the Add method here, which if the product is available, adds it to the list. We have already written a test for this method.
public class ProductServiceTests
{
public void Add_WhenProductIsAvailable_ShouldAddProductToTheList()
{
var product = new Product { Quantity = 1 };
var productService = new ProductService(new ProductValidator());
productService.Add(product);
Assert.AreEqual(1, productService.Products.Count);
}
}
The test passes, everything is fine, but let's take a look at our assertion. Is it readable? Do you know what the first parameter of the Assert.AreEqual method is? Do you know what the second parameter is? Is the order correct? Unfortunately, it's not that intuitive and I often came across tests where these parameters were given in the opposite order.
To have a better comparison, let's write the same test, but using assertions from the FluentAssertions library. To do this, you first need to install the FluentAssertions library via Nuget. Just open "Manage Nuget Packages" for the project with tests and install the FluentAssertions library.
Then you need to add using FluntAssertions in the class with tests and we can use fluent assertions.
using FluentAssertions;
Now let's try to write the same test, but using the assertions from the FluentAssertions library.
public class ProductServiceTests
{
public void Add_WhenProductIsAvailable_ShouldAddProductToTheList()
{
var product = new Product { Quantity = 1 };
var productService = new ProductService(new ProductValidator());
productService.Add(product);
Assert.AreEqual(1, productService.Products.Count);
}
[Test]
public void Add_WhenProductIsAvailable_ShouldAddProductToTheList_FluentAssertions()
{
var product = new Product { Quantity = 1 };
var productService = new ProductService(new ProductValidator());
productService.Add(product);
productService.Products.Count.Should().Be(1);
}
}
When using FluentAssertions, we have a lot of methods that make it easier for us to write assertions. Among others, we can use the Should() Be() methods, as we did in our case, but also Should() BeGreaterThan(), BeLessThan(), NotBe() and many others. Of course, there are different methods for each type here.
Comparing these 2 assertions:
Assert.AreEqual(1, productService.Products.Count);
productService.Products.Count.Should().Be(1);
We can see that assertions written using FluentAssertions library extension methods are much more readable and intuitive. We don't have to wonder what is the expected value and what is the actual value. And this is the first advantage of this library.
Of course, the FluentAssertions library has many different methods that you should get to know, but this is a topic for a separate article, in this article I wanted to present you only the 2 most important advantages of this library.
Another advantage is better messages when our tests fail. I will now make a mistake in our tests and compare the messages we get in both cases. I will only change the value of the Quantity property to 0 for both tests.
public class ProductServiceTests
{
public void Add_WhenProductIsAvailable_ShouldAddProductToTheList()
{
var product = new Product { Quantity = 0 };
var productService = new ProductService(new ProductValidator());
productService.Add(product);
Assert.AreEqual(1, productService.Products.Count);
}
[Test]
public void Add_WhenProductIsAvailable_ShouldAddProductToTheList_FluentAssertions()
{
var product = new Product { Quantity = 0 };
var productService = new ProductService(new ProductValidator());
productService.Add(product);
productService.Products.Count.Should().Be(1);
}
}
After running both tests are red, meaning they fail. Each one returned a different message.
Assert.AreEqual: "Expected: 1 But was: 0".
Fluent Assertions: "Expected productService.Products.Count to be 1, but found 0".
However, in the case of FluentAssertions, it is much more detailed, you know immediately, even without knowing these tests, where the error is and what went wrong. So I think that this is a big plus. For my part, I recommend that you familiarize yourself with the FluentAssertions library, I use it every day and it helps me a lot in writing good and readable unit tests.
It is worth reading the documentation of this library, where you will find descriptions of how to test individual test scenarios.
Unit Testing School
If you would like to learn how to write unit tests in C#/.NET applications, consider joining the Unit Testing School - [here].
SUMMARY
This is what fluent assertions look like, written using the FluentAssertions library. It is worth reading the documentation of this library, where you will find detailed descriptions of how to test different test scenarios exactly.
If you liked this article, be sure to join my community. Sign up for the free newsletter, where every week I share valuable materials, especially regarding C# and the .NET platform (free subscription - newsletter).