Should You Pay for FluentAssertions? A Comparison with Shouldly

Introduction

Cosmin Vladutu
2 min readJan 21, 2025

As most of you already know, FluentAssertion from V8 will not be free anymore. I won’t argue about why this happened, if it’s a good thing or a bad thing and I will also not teach you how to change it to Shouldly. To do that, I encourage you to read an article that you can find here. I can’t add anything more to it, and to rewrite, it doesn’t make any sense.

What I want to share with you is what you are doing or could do with Fluent Assertions and what you can’t do with Shouldly.

FluentAssertions vs Shouldly

  1. Assertion Scope — this gives you even more clarity by grouping multiple assertions by using AssertionScope. If you are one of those guys who say that you should NEVER use multiple asserts in tests, then it doesn’t matter what I would say in regards to this, it is just…not applicable to you. I like using it and seeing a “summarized fail report”, of course where and when it makes sense.
using (new AssertionScope())
{
result.Should().NotBeNull();
result.FirstName.Should().Be("Vladutu");
result.LastName.Should().Be("Cosmin");
}

Shouldly doesn’t have an alternative to this, and basically, it will fail at the first condition which is not met.

2. Shouldly’s ShouldBeEquivalentTo vs BeEquivalentTo from FluentAssertions — however you want to look at it, you will eventually accept the fact that BeEquivalentTo is way more powerful when comparing complex objects, especially when you have nested properties.

3. Collections Assertions — In Shouldly you have ShouldBeInOrder and ShouldContain, but it’s harder to test specific things from the collection.

collection.Should().SatisfyRespectively(
first =>
{
first.Id.Should().Be(1);
first.Name.Should().StartWith("J");
first.Attributes.Should().NotBeNull();
},
second =>
{
second.Id.Should().Be(2);
second.Name.Should().EndWith("e");
second.Attributes.Should().NotBeEmpty();
});

4. Extensibility — way more limited. You have a good example of what I am thinking about in the Fluent Assertions documentation here.

5. Predicate Assertions — As far as I know, Shouldly doesn’t have something similar

result.Should().Match(r => r.Name == "Cosmin" && r.Age > 25);

Probably there are more features provided by Fluent Assertions, that aren’t in Shouldly, but those are the things that are the most important to me. At the same time, I must accept the fact that Shouldly has a simpler syntax and it’s easier to be used by beginners.

Conclusion

If you are using FluentAssertions only to make the code more readable, and by this I mean, only the Should().Be(“whatever”), then probably it won’t make any sense to pay (or ask to company to pay) the subscription. If you are doing a little bit more, and really use it at its true potential, well…then it makes sense to dig a little bit deeper. To rewrite the tests that aren’t fixed by just changing a method, might cost more than the licenses themselves.

--

--

Cosmin Vladutu
Cosmin Vladutu

Written by Cosmin Vladutu

Software Engineer | Azure & .NET Full Stack Developer | Leader

No responses yet