I’ve been writing some chef cookbooks recently. And you often see tests in chef that looks something like

expect(chef_run).to(create_template('/opt/xyz.yml')
    .with_cookbook('other_cookbook'))

And, when I came back to writing C# again, a Fluent Assertions statement seemed familiar.

actual.Should().Contain(expected).And.HaveCount(2);

I haven’t seen the extensibility points of Fluent Assertions library talked about much. And I am starting to think, this is the real advantage Fluent Assertions library brings compared to the built in assertion methods from the test framework.

For example, doesn’t this assertion look pretty? What would be the equivalent without using Fluent Assertions?

fakeFileStore.Should().HaveFileAt("/etc/xyx.txt").Which
    .Should().MatchBase64EncodedStringContent(content);

When using FurlClient for example, the library comes with an HttpTest class that helps with testing.

var httpTest = new HttpTest();
httpTest.ForCallsTo("https://google.com")
    .RespondWithJson(new { foo = "bar" });

However, the verification or assertion error messages are not very useful if you have a long chain of verifications.

httpTest.ShouldHaveCalled("https://google.com")
    .WithVerb(HttpMethod.Post)
    .WithBearerToken("valid_token")
    .WithContentType("application/json")
    .WithRequestBodyJson(new { foo = "bar" });

You’ll only get a generic error message saying one of those things didn’t match. The failure message doesn’t tell you which part of the assertion failed.

However, re-writing them using Fluent Assertions custom extensions can provide you with much better failure messages at exactly the point at which the verification fails.

httpTest.Should().HaveCalled("https://google.com").Which
    .Should().HaveVerb(HttpMethod.Post).And
    .HaveBearerToken("valid_token").And
    .HaveContentType("application/json").And
    .HaveRequestJsonBody(new { foo = "bar" });

You can also verify that the request or response JSON body matches a JSON schema as well.

httpTest.Should().HaveCalled("https://google.com").Which
    .Should().MatchRequestSchema("./req-schema.json").And
    .MatchResponseSchema("./res-schema.json");

Fluent Assertions library provides you with a few built in extension methods for assertions. However, the real power is when you start creating your own extension methods for the classes in your code base. This can help with readability of the tests, reduce blotted assertions, discover-ability and re-usability of assertion methods.

There are a number of Fluent Assertions nuget packages, but not a lot compared to how powerful of a feature this is.