Comments (20)
We had a similar discussion in #2263, where I also added some additional use cases and benefits for having Satisfy
available on single objects in addition to collections.
I like this idea 👍
A next step would be to dig into which XyzAssertions
(perhaps multiple) this should be available from.
from fluentassertions.
A next step would be to dig into which XyzAssertions (perhaps multiple) this should be available from.
IIRC this lists all root Assertion types and from that it seems to me that implementing the API on only ReferenceTypeAssertions
is fine. That also aligns with the location of the existing ReferenceTypeAssertions.Match
.
I vote for adding Satisfy
over overloading Match
.
from fluentassertions.
@jnyrup I'm sorry, I didn't find that specific issue when I searched, but it does look similar to what I'm proposing here.
from fluentassertions.
Let's go for Satisfy
then. @siewers you're good to go.
from fluentassertions.
Sounds good.
I didn't see any other example of nested test classes, so I tried to follow the pattern of the tests I was modifying. It would be nice if there was some guidelines on the test class pattern (I didn't find any when I looked through the contribution guidelines).
from fluentassertions.
A next step would be to dig into which XyzAssertions (perhaps multiple) this should be available from.
Can you pick that up @siewers ? When we have the full list, we can approve the API.
from fluentassertions.
@dennisdoomen I'm a bit unsure how to proceed. I don't have an overview of the FluentAssertions architecture and design. I might simply start by "brute-forcing" the idea in and take it from there. It's usually the easiest way for me to learn.
from fluentassertions.
Sure, that could work.
from fluentassertions.
I've looked into it and I must admit it doesn't seem possible to do what I'm asking. Because I need the Should()
extension to be generic, I think this would be a major breaking change and likely not feasible.
@jnyrup Do you have any suggestions on how to achieve this?
from fluentassertions.
The closest thing I've been able to get is where I explicitly make the Satisfy
method generic, similar to Match
, so it would look something like this:
SomeType subject = new SomeType();
subject.Should()
.Satisfy<SomeType>(s => s.Property1.Should().NotBeEmpty());
/* Etc. */
The generic parameter on Satisfy
could be constrained to match TSubject
, but it doesn't make any difference since TSubject
is lost when using ObjectAssertions
that are not already built using one of the know type extensions of Should
.
from fluentassertions.
The closest thing I've been able to get is where I explicitly make the
Satisfy
method generic, similar toMatch
, so it would look something like this:
That's the only way I can think of to make this work. You would have to cast the object
back to TSubject
, but that could be an acceptable tradeoff.
from fluentassertions.
In that case, I believe an additional overload to Match
that accepts an element inspector would be a better solution.
It would also make sense to reuse the existing terminology of "match" which makes sense to me since I'm asking whether it matches either a predicate or an inspector.
from fluentassertions.
I've added similar tests as what is on the current Match
method:
Using predicates:
someObject.Should().Match(o => o == null, "it is not initialized yet");
someObject.Should().Match((SomeDto d) => d.Name.Length == 0, "it is not initialized yet");
Using element inspectors:
someObject.Should().Match<object>(o => o.Should().BeNull("it is not initialized yet"));
someObject.Should().Match<SomeDto>(d => d.Name.Should().HaveLength(0, "it is not initialized yet"));
It is a bit longer, but it is a lot more expressive this way. I can write assertions on each property with the expectations and "because", which, in the end, produces a lot more meaningful output.
It will also allow you to do more complex assertions:
// Arrange / Act
var someObject = new SomeDto
{
Name = "Dennis Doomen",
Age = 36,
Birthdate = new DateTime(1973, 9, 20)
};
// Assert
someObject.Should().Match<SomeDto>(d =>
{
d.Name.Should().Be("Someone Else");
d.Age.Should().BeGreaterThan(40, because: "the person is at least 40");
d.Birthdate.Should().BeAfter(new DateTime(1982, 9, 22));
});
This will return the following error message:
Expected someObject to match inspector, but the inspector is not satisfied:
Expected d.Name to be the same string, but they differ at index 0:
↓ (actual)
"Dennis Doomen"
"Someone Else"
↑ (expected).
Expected d.Age to be greater than 40 because the person is at least 40, but found 36 (difference of -4).
Expected d.Birthdate to be after <1982-09-22>, but found <1973-09-20>.
I've also tested with nested assertions. It's a bit complex, but I find it a lot more readable (arguably, this is probably too much, but it's just there as an example).
// Arrange / Act
var someObject = new SomeComplexDto
{
Person = new SomeDto
{
Name = "Buford Howard Tannen",
Age = 48,
Birthdate = new DateTime(1937, 3, 26)
},
Address = new AddressDto
{
Street = "Mason Street",
Number = "1809",
City = "Hill Valley",
Country = "United States",
PostalCode = "CA 91905"
}
};
// Assert
someObject.Should().Match<SomeComplexDto>(dto =>
{
dto.Person.Should().Match<SomeDto>(person =>
{
person.Name.Should().Be("Biff Tannen");
person.Age.Should().Be(48);
person.Birthdate.Should().Be(new DateTime(1937, 3, 26));
});
dto.Address.Should().Match<AddressDto>(address =>
{
address.Street.Should().Be("Mason Street");
address.Number.Should().Be("1809");
address.City.Should().Be("Hill Valley, San Diego County, California");
address.Country.Should().Be("United States");
address.PostalCode.Should().Be("CA 91905");
});
});
This will produce the following output:
Expected someObject to match inspector, but the inspector is not satisfied:
Expected dto.Person to match inspector, but the inspector is not satisfied:
Expected person.Name to be the same string, but they differ at index 1:
↓ (actual)
"Buford Howard Tannen"
"Biff Tannen"
↑ (expected).
Expected dto.Address to match inspector, but the inspector is not satisfied:
Expected address.City to be "Hill Valley, San Diego County, California" with a length of 41, but "Hill Valley" has a length of 11, differs near "y" (index 10).
from fluentassertions.
There's already a Match
, so this can't work. But a Satisfy
method would also align well with the one on collections.
from fluentassertions.
I did implement it as an overload for Match
so it does work, but if Satisfy
is better that's fine with me. I just thought it was more natural to have the option to use either predicates or inspectors.
Satisfy
is also overloaded with both predicates and inspectors.
from fluentassertions.
Great! I'll introduce the Satisfy
method.
On a side-note, I'm getting hit by an annoying bug in Rider, causing the tests to fail due to Rider trimming whitespaces inside raw string literals when saving.
I ended up splitting the Match and Satisfy tests into separate partial classes, which I hope is okay.
from fluentassertions.
from fluentassertions.
I ended up splitting the Match and Satisfy tests into separate partial classes, which I hope is okay.
Yes, but as a separate commit or PR please. Also, add a nested class to the root of each partial class to provide a kind of grouping and context so you don't have to repeat words like match and satisfy.
from fluentassertions.
There are some guidelines in #1340 (pinned to the top of the issues page), but I agree it could be a bit better.
from fluentassertions.
I'm so sorry, I read that, but apparently, I wasn't thorough enough. I'll update the tests to reflect that.
from fluentassertions.
Related Issues (20)
- Library is not compatible with .NET MAUI 8.0.6 HOT 4
- Add feature to check if an XElement or XAttribute is absent within the XDocument HOT 25
- Null reference exception when using custom comparer in equivalency options HOT 7
- [Feature]: Multi dimension arrays assertions HOT 10
- WithInnerException<T>() needs the type as a parameter HOT 2
- `Should().BeEquivalentTo` failing for identical objects HOT 3
- FluetntAssertion doesn't work correctly for records HOT 8
- Equivalency assertion option Excluding outputs "value(...<>c__DisplayClass).variableName" in some instances HOT 2
- Add string-option for ignoring newline style HOT 2
- Unexpected default equivalency behaviour with interfaces HOT 3
- ArgumentOutOfRangeException in FluentAssertions.Equivalency.Tracing.StringBuilderTraceWriter.ToString() HOT 8
- FluentAssertions: using a NullorEqual string EqualityComparer still returns a type difference error HOT 2
- [API Proposal]: Allow to assert RegEx matched groups HOT 3
- BeXmlSerializable does not respect XmlIgnoreAttribute HOT 5
- Use StringSyntaxAttribute to provide IDE support for proper reasons HOT 2
- [API Proposal]: Parsability of strings HOT 18
- Add AllSatisfyOrEmpty for GenericCollection HOT 4
- AssertionScope w/explicit name AND DetermineCallerIdentity doesn't work as expected
- [Feature]: SetEquals, unordered equal for collections HOT 1
- [Feature]: Compile time warning/error for chaining Should() after a null conditional (?.) HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fluentassertions.