26

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?

Community
  • 1
  • 1
YMM
  • 632
  • 1
  • 10
  • 21

4 Answers4

48

You can do this with assertion scopes like this:

using (new AssertionScope())
{
    5.Should().Be(10);
    "Actual".Should().Be("Expected");
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
RonaldMcdonald
  • 576
  • 6
  • 7
9

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);
});
Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73
2

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.

Rob Prouse
  • 22,161
  • 4
  • 69
  • 89
  • 14
    For reference purposes, the equivalent in FluentAssertions is the `AssertionScope`. – Dennis Doomen Aug 30 '17 at 05:44
  • @DennisDoomen If I use `AssertionScope` and call two methods within it, each having a single assert, I get the following message in Test Explorer: Expected value to be 2, but found 1. Expected value to be 4, but found 3. Can I customize this message? For example, include method name in it, so I can see in which method the assertion fails? – YMM Aug 30 '17 at 17:33
  • Each of these methods except an extra parameter to provide the reason of the expected outcome. – Dennis Doomen Sep 01 '17 at 05:48
0

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.

Daan
  • 2,478
  • 3
  • 36
  • 76