Skip to content

GenericCollectionAssertions.SatisfyRespectively: message formatting fails when nested message contains braces #1092

@kennep

Description

@kennep

Description

When using GenericCollectionAssertions.SatisfyRespectively, and the nested assertion failure message contains braces, message formatting will fail with a System.FormatException.

This happens because FailWith is called with a formatting message containing braces, but with zero message arguments, in these places:

SatisyRespectively (fails when the reason variable is a string containing braces):

   414              if (failuresFromInspectors.Any())
   415              {
   416                  string failureMessage = "Expected {context:collection} to satisfy all inspectors{reason}, but some inspectors are not satisfied:"
   417                      + Environment.NewLine
   418                      + string.Join(Environment.NewLine, failuresFromInspectors.Select(x => x.IndentLines()));
   419                  Execute.Assertion
   420                      .BecauseOf(because, becauseArgs)
   421                      .FailWith(failureMessage);
   422              }

CollectFailuresFromInspectors (fails when failures variable is a string containing braces):

   442                      if (inspectorFailures.Length > 0)
   443                      {
   444                          // Adding one tab and removing trailing dot to allow nested SatisfyRespectively
   445                          string failures = string.Join(Environment.NewLine, inspectorFailures.Select(x => x.IndentLines().TrimEnd('.')));
   446                          // FailWith formatting is not used because of extra quotes being added.
   447                          Execute.Assertion
   448                              .FailWith($"At index {index}:{Environment.NewLine}{failures}");
   449                      }

Complete minimal example reproducing the issue

byte[][] aa = { new byte[]{1} };

aa.Should().SatisfyRespectively( e => {
	e.Should().BeEquivalentTo(new byte[]{2, 3, 4});
});

Expected behavior:

Assertion failure with a message indicating that not all inspectors were satisfied, and that the expected and actual arrays at element 0 had different lengths.

Actual behavior:

Stack trace:

   System.FormatException : Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
  Stack Trace:
     at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.Format(String format, Object[] args)
   at FluentAssertions.Execution.MessageBuilder.FormatArgumentPlaceholders(String failureMessage, Object[] failureArgs) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Execution/MessageBuilder.cs:line 90
   at FluentAssertions.Execution.MessageBuilder.Build(String message, Object[] messageArgs, String reason, ContextDataItems contextData, String identifier, String fallbackIdentifier) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Execution/MessageBuilder.cs:line 40
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Execution/AssertionScope.cs:line 178
   at FluentAssertions.Execution.AssertionScope.FailWith(String message, Object[] args) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Execution/AssertionScope.cs:line 200
   at FluentAssertions.Collections.GenericCollectionAssertions`1.SatisfyRespectively(IEnumerable`1 expected, String because, Object[] becauseArgs) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs:line 419
   at FluentAssertions.Collections.GenericCollectionAssertions`1.SatisfyRespectively(Action`1[] elementInspectors) in /home/kenneth/Projects/3rdParty/fluentassertions/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs:line 362

Versions

Tested with
FluentAssertions 5.7.0
FluentAssertions from master: fdc2c7d
.Net Core 2.2 (Linux)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions