Multiple assertions using Fluent Assertions library

14.5k views Asked by At

It seems that Fluent Assertions doesn't work within NUnit's Assert.Multiple block:

Assert.Multiple(() =>
    {
        1.Should().Be(2);
        3.Should().Be(4);
    });

When this code is run, the test fails immediately after the first assertion, so the second assertion is not even executed.

But, if I use NUnit's native assertions, I get the results I want:

Assert.Multiple(() =>
    {
        Assert.That(1, Is.EqualTo(2));
        Assert.That(3, Is.EqualTo(4));
    });

And the output contains details on both failures:

Test Failed - ExampleTest()

Message: Expected: 2 But was: 1

Test Failed - ExampleTest()

Message: Expected: 4 But was: 3

How can I get similar results using Fluent Assertions with NUnit?

4

There are 4 answers

0
RonaldMcdonald On BEST ANSWER

You can do this with assertion scopes like this:

using (new AssertionScope())
{
    5.Should().Be(10);
    "Actual".Should().Be("Expected");
}
3
Rob Prouse On

Sorry, short answer is that you can't currently get the same results with Fluent assertions. The NUnit assertions have special logic in them that knows they are in a multiple assertion block. In that case, they don't throw an exception on failure, but instead register the failure with the parent multiple assert which will report the error when it is complete.

Fluent assertions will need to do the same thing internally. That could be as simple as chaining to the NUnit assertions, or even just calling Assert.Fail. I would recommend filing an issue with the Fluent assertions project. Feel free to point them to me on GitHub (@rprouse) if they need help on how the NUnit internals work.

2
Dariusz Woźniak On

You may either:

1: Use AssertionScope (as pointed by @RonaldMcdonald):

using (new AssertionScope())
{
  (2 + 2).Should().Be(5);
  (2 + 2).Should().Be(6);
}

Or:

2. Use FluentAssertions.AssertMultiple NuGet package (the tiny package created by myself):

AssertMultiple.Multiple(() =>
{
    (2 + 2).Should().Be(5);
    (2 + 2).Should().Be(6);
});

And, when you import static member:

using static FluentAssertions.AssertMultiple.AssertMultiple;

//...

Multiple(() =>
{
    (2 + 2).Should().Be(5);
    (2 + 2).Should().Be(6);
});
1
Daan On

When using a recent version of C# (after 6), you can simply use ValueTuples.

Here is an example I use in one of my unit tests made with xUnit and FluentAssertions:

[Theory]
[InlineData(70.01, 180, 1.80, 21.61)]
public void ValueTupleTest(decimal weightInKg, int lengthInCm, decimal expectedLengthInM, decimal expectedBmi)
{
    var instance = new HealthDescription(weightInKg, lengthInCm);
    (instance.LengthInM, instance.Bmi, instance.WeighthInKg).Should()
                .Be((expectedLengthInM, expectedBmi, weightInKg));
}

When using ValueTuples, you can easily wrap multiple values into one object. So formally, it's still one assertion. However, there are multiple validations effectively.