An Example of FluentAssertions migration

·

2 min read

Create a namespace (folder) in your test project, e.g. Assertions. This shall be the new namespace to replace the FluentAssertions.

Any of your test class file which uses FluentAssertions would have using FluentAssertions; on it. We now try to migrate them one by one first.

For example, we start with one of my test file MatchFinder_Test.cs before the migration:

using FluentAssertions;
using PeterDoStuff.Games;

namespace PeterDoStuff.Test
{
    [TestClass]
    public class MatchFinder_Test
    {
        [TestMethod]
        public void _01_New_Add()
        {
            var game = MatchFinder.New();
            game.Cells.Should().HaveCount(0);
            game.Add(0);
            game.Cells.Should().HaveCount(1);
        }
        ...
    }
}

Now, comment or delete the line using FluentAssertions;

This will make your IDE highlight all the .Should() extensions of FluentAssertions.

Now go to your folder Assertions created before, and create a class file named AssertionExtensions.cs

Seeing in MatchFinder_Test.cs highlighting game.Cells.Should().HaveCount(0);, we shall create the Collection Assertion first.

Turn the class AssertionExtensions to be public static, and create the Should() extension method and the CollectionAssertion<T> class:

public static class AssertionExtensions
{
    public static CollectionAssertion<T> Should<T>(this IEnumerable<T> @this)
    {
        return new CollectionAssertion<T>(@this);
    }
}

public class CollectionAssertion<T>(IEnumerable<T> value)
{
}

In the MatchFinder_Test.cs, add in using PeterDoStuff.Test.Assertions; while still commenting the using FluentAssertions;

You will find that there is no error of the .Should() for line of code like game.Cells.Should().HaveCount(0);. However, there is still error for .HaveCount(0), which we will implement now.

Implement HaveCount(int) for the CollectionAssertion class:

public class CollectionAssertion<T>(IEnumerable<T> value)
{
    public void HaveCount(int expectedCount)
    {
        Assert.AreEqual(expectedCount, value.Count());
    }
}

I guess at this point you’ve the Gizz of it. Now go on to create the necessary Assertion classes and their methods until you cover all the APIs that you have used from FluentAssertions. For example:

public static class AssertionExtensions
{
    public static NullableDateTimeAssertions Should(this DateTime? @this)
    {
        return new NullableDateTimeAssertions(@this);
    }
}

public class NullableDateTimeAssertions(DateTime? value)
{
    public void BeNull()
    {
        Assert.IsNull(value);
    }

    public void BeOnOrAfter(DateTime expectedValue)
    {
        Assert.IsNotNull(value);
        Assert.IsTrue(value.Value >= expectedValue);
    }
}

At the end, I just need 2 more Assertion classes BooleanAssertion and IntegerAssertion to migrate my MatchFinder_Test.cs from using FluentAssertions to using the homemade version that have the same interfaces.