Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work with FluentAssertions 6.4.0 #72

Closed
alexeyshockov opened this issue Jan 24, 2022 · 12 comments · Fixed by #73
Closed

Does not work with FluentAssertions 6.4.0 #72

alexeyshockov opened this issue Jan 24, 2022 · 12 comments · Fixed by #73

Comments

@alexeyshockov
Copy link

After FluentAssertions 6.4.0 release where fluentassertions/fluentassertions#1737 was merged, this library now conflicts with the main one, so I have a bunch of errors like

OrderTests.cs(45,18): error CS0121: The call is ambiguous between the following methods or properties: 'FluentAssertions.AssertionExtensions.Should(System.Net.Http.HttpResponseMessage)' and 'FluentAssertions.HttpResponseMessageFluentAssertionsExtensions.Should(System.Net.Http.HttpResponseMessage?)'

I have no idea how I can resolve this manually.

Do you know a way to use the latest FluentAssertions and FluentAssertions.Web?

@adrianiftode
Copy link
Owner

adrianiftode commented Jan 24, 2022

This is unfortunate and probably the end of FluentAssertions.Web

@adrianiftode
Copy link
Owner

At least using Should().BeXXX() won't be available for FluentAssertions.Web anymore. What I can do is to migrate all Should().BeXXX to ShouldBeXXX which is not how FA users are used with.

@adrianiftode adrianiftode pinned this issue Jan 24, 2022
@adrianiftode
Copy link
Owner

adrianiftode commented Jan 24, 2022

@alexeyshockov thanks for posting the issue. Unfortunately, the solution will introduce some breaking changes and will drive the FluentAssertions.Web into an unconventional usage.

I think the best way to solve this is to rename the Should() extension method into something else like ShouldIt. Then the things will look like:

Before After
response.Should().Be200Ok() response.ShouldIt().Be200Ok()
response.Should().BeAs(new { name = "Adrian"} ) response.ShouldIt().BeAs(new { name = "Adrian"} )
response.Should().HaveHeader() ) response.ShouldIt().HaveHeader()
------------- ----so on---------

The good part of this solution is the fact all FluentAssertions.Web assertions have better discoverability during the development time, as after you type ShouldIt() followed by . (dot), then the IDE will show you the scoped assertions to the HttResponseMessage with priority. The bad part is no one expects the ShouldIt naming from a FluentAssertions plugin

Alternatively would be to introduce extension methods for all existing assertions, but this would add an obsolete usage like FA had with ShouldBeEquivalentTo. The things would look like

Before After
response.Should().Be200Ok() response.ShouldBe200Ok()
response.Should().BeAs(new { name = "Adrian"} ) response.ShouldBeAs(new { name = "Adrian"} )
response.Should().HaveHeader() ) response.ShouldHaveHeader()
------------- ----so on---------

Both solutions would be resilient to FA's development in the way that FA will never introduce such extension methods.

Any suggestion would be great.

@alwo23
Copy link

alwo23 commented Jan 25, 2022

I find the "ShouldIt" suggestion a little unwieldy to read as it turns the assertion into a question, so I would prefer "ShouldBe200Ok(), ShouldHaveHeader(), ..." variant.

If "we" are willing to deviate from FA's "Should" paradigm, we could simply switch to "Shall":
response.Shall().Be200Ok()
response.Shall().HaveHeader()
Or "IsExpectedTo":
response.IsExpectedTo().Be200Ok()
response.IsExpectedTo().HaveHeader()

@alwo23
Copy link

alwo23 commented Jan 25, 2022

@adrianiftode I chose the 'we' to express that I really like what you gave us here and that I as a users feel like we users shall help come to a good solution for all of us ...
... and I'm glad that you already stroked through the "end of FluentAssetions.Web" above

@adrianiftode
Copy link
Owner

@alwo23 thanks, these are good suggestions. I was thinking also to invert the words.

response.ItShould().XXXX

But I really like the Shall one, as it has LOTR vibes 💍

@alexeyshockov
Copy link
Author

IMO any name will be bad here, because having a separate extension method is an ugly solution anyway. So either Shall() or ItShould() work.

Have you considered making a PR to the FluentAssertions itself, BTW? If they have a matcher for HTTP response now, with basic assertions, maybe it's a good time to migrate the rest there? Just asking, do not know how complicated is it.

@jflevesque
Copy link

FluentAssertions 6.4.0 have added equivalent methods, such as Should().HaveStatusCode(HttpStatusCode.ServiceUnavailable). I wasn't much to simply refactor and use those methods instead.

@adrianiftode
Copy link
Owner

One of the important features from FluentAssertions.Web is outputting the HTTP response and request when the test fails, which is not present in the FluentAssertions 6.4.0. And other APIs like BeAs, Satisfy. If you only need HaveStatusCode and happy with the results when it fails, then FluentAssertions 6.4.0 should be more than fine.

@jflevesque
Copy link

jflevesque commented Jan 25, 2022

In that case, can't you move those extension methods to the new HttpResponseMessageFluentAssertionsExtensions class from FluentAssertions?

@adrianiftode
Copy link
Owner

I received a good suggestion from the FA maintainers and testing it right now. I will have to create extensions over their Primitives.HttpResponseMessageAssertions. This is really good news as there is no rename. Just it will take a while as I will have to do it for a bunch of methods.

   /// <summary>
       /// Asserts that a HTTP response has the HTTP status 400 BadRequest
       /// </summary>        
       /// <param name="because">
       /// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
       /// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
       /// </param>
       /// <param name="becauseArgs">
       /// Zero or more objects to format using the placeholders in <see paramref="because" />.
       /// </param>
       public static AndConstraint<BadRequestAssertions> Be400BadRequest(
#pragma warning disable 1573
           this Primitives.HttpResponseMessageAssertions<Primitives.HttpResponseMessageAssertions> parent,
#pragma warning restore 1573
           string because = "", params object[] becauseArgs)
           => new HttpResponseMessageAssertions(parent.Subject).Be400BadRequest(because, becauseArgs);

adrianiftode added a commit that referenced this issue Jan 25, 2022
Fix the conflicts between FA 'Should' extension
   and FA.Web 'Should' extension

Add a test to maintain the sync between FA.Web assertions
and Primitives.HttpResponseMessageAssertions

Closes #72
adrianiftode added a commit that referenced this issue Jan 25, 2022
Fix the conflicts between FA 'Should' extension
   and FA.Web 'Should' extension

Add a test to maintain the sync between FA.Web assertions
and Primitives.HttpResponseMessageAssertions

Closes #72
adrianiftode added a commit that referenced this issue Jan 25, 2022
Fix the conflicts between FA 'Should' extension
   and FA.Web 'Should' extension

Add a test to maintain the sync between FA.Web assertions
and Primitives.HttpResponseMessageAssertions

Closes #72
@adrianiftode
Copy link
Owner

Thank you all for your feedback and a big shout out to the FluentAssertions team for providing the actual solution.

@adrianiftode adrianiftode unpinned this issue Jan 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants