fluentassertions icon indicating copy to clipboard operation
fluentassertions copied to clipboard

Add `ForConstraint` to `IAssertionScope`

Open ITaluone opened this issue 3 years ago • 2 comments

Before you file a bug, have you:

  • Tried upgrading to newest version of Fluent Assertions, to see if your issue has already been resolved and released?
  • Checked existing open and closed issues, to see if the issue has already been reported?
  • Tried reproducing your problem in a new isolated project?
  • Read the documentation?
  • Considered if this is a general question and not a bug?. For general questions please use StackOverflow.

Description

Is there a good reason why ForConstraint is not available in an IAssertionScope, but only in the AssertionScope implementation? Reason for this change is, that you can not chain an ForConstraint after a Then, resulting in quite longish sets of Execute.Assertion...

Complete minimal example reproducing the issue

Complete means the code snippet can be copied into a unit test method in a fresh C# project and run. Minimal means it is stripped from code not related to reproducing the issue.

E.g.

Execute.Assertion
    .BecauseOf(because, becauseArgs)
    .WithExpectation($"Some expectation {0}}{{reason}}, ", parameter)
    .ForCondition(somethingShouldBeTrue)
    .FailWith("but cool error.")
    .Then
    .ForConstraint(occurrenceConstraint, actualCount) // this line here
    .FailWith($"Other cool error {{0}}{{reason}}, but found {{1}}.",
        coolParameter, bla);

Expected behavior:

Chaining a ForConstraint should also work after Then

Actual behavior:

Does not :)

Versions

  • Which version of Fluent Assertions are you using? 6.6.0

ITaluone avatar Apr 29 '22 04:04 ITaluone

I can't remember at the top of my head why we didn't also include it on IAssertionScope in v6. Adding it now is technically a breaking change.

jnyrup avatar Apr 29 '22 21:04 jnyrup

Ok, so if we add it at v7 take the following also into consideration: for now you have to include .WithExpectation() twice in the statement. First place: as shown in the example and second before the .ForConstraint(). The only difference is: the second .WithExpectation() includes the reportable for the occurrence {expectedOccurrence}.

To handle this, I have two possible solutions:

  1. Add a new method e.g. .WithReportable() or something like that, where you can pass down the reportable WithExpectation() should care of
  2. remove the {expectedOccurrence} only at .FailWith() after a .ForConstraint()

Hope this is clear :)


Execute.Assertion
    .BecauseOf(because, becauseArgs)
    .WithExpectation($"Some expectation {0}}{{reason}}, ", parameter)
    .WithReportabe("expectedOccurrence")
    .ForCondition(somethingShouldBeTrue)
    .FailWith("but cool error.")
    .Then
    .ForConstraint(occurrenceConstraint, actualCount) // this line here
    .FailWith($"Other cool error {{0}}{{reason}}, but found {{1}}.",
        coolParameter, bla);

IT-VBFK avatar Apr 30 '22 06:04 IT-VBFK

While implementing this I changed my mind about the second .WithExpectation(), because

  • it affects mostly extensions
  • you want a different expectation message sometimes

IT-VBFK avatar Sep 26 '23 08:09 IT-VBFK

This is also related to #2253

dennisdoomen avatar Sep 28 '23 09:09 dennisdoomen