-
Notifications
You must be signed in to change notification settings - Fork 731
Description
Background and motivation
When I'm asserting many properties on multiple instances, I often find it hard to keep track of the context of what I'm asserting.
Like with collections, we have a collection.Should().AllSatisfy(item => { /* do FluentAssertions on item here */ }, but I feel like this is missing for single instances.
The closest thing I've found is instance.Should().Match(/* something that returns true or false */), which is not really fluent as I see it.
The alternative is to do object comparison, where I need to construct the expected object before and then do instance.Should().BeEquivalentTo(expected).
What I'm suggesting is to allow scoped assertions on a single instance, like this:
var person = new Person { Name = "Peter", Age = 30 };
person.Should().Satisfy(p =>
{
p.Name.Should().StartWith("P");
p.Age.Should().BeGreaterThan(25);
});Providing this, also allows me to extract generic assertions as methods, which can be reused.
I am aware that the above is equivalent to this:
var person = new Person { Name = "Peter", Age = 30 };
person.Name.Should().StartWith("P");
person.Age.Should().BeGreaterThan(25);However, if I have many assertions where the variable names are long, it becomes quite a lot of noise in the tests.
For instance:
Person someInstanceOfPersonComingFormACallbackFromNSubstitute;
someInstanceOfPersonComingFormACallbackFromNSubstitute.Name.Should().StartWith("P");
someInstanceOfPersonComingFormACallbackFromNSubstitute.Age.Should().BeGreaterThan(25);This would be, IMHO, more readable like this:
Person someInstanceOfPersonComingFormACallbackFromNSubstitute;
someInstanceOfPersonComingFormACallbackFromNSubstitute.Should().Satisfy(p =>
{
p.Name.Should().StartWith("P");
p.Age.Should().BeGreaterThan(25);
});I am well aware that there might be a good reason for this to not exist and that it's possible to create a simple extension method like this:
public static void ShouldSatisfy<T>(this T actual, Action<T> assert) where T : class
{
assert(actual);
}I also understand that this approach could lead to confusion since the Satisfy() method would have to exist on all types being asserted.
It might also be the case that my tests are too complex, however, it's an integration test, so I have a lot to assert, which makes the need clear to me.
Alternative Concerns
No response
Are you willing help with a pull-request?
Yes, please assign this issue to me.