-
Notifications
You must be signed in to change notification settings - Fork 732
Introduce assertions for StatusCode of HttpResponseMessage #1737
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
Merged
dennisdoomen
merged 20 commits into
fluentassertions:master
from
swisspost:feature/HttpResponseMessageAssertions
Jan 10, 2022
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
0e36272
Introduce new assertions for StatusCode of HttpResponseMessage (#1698)
mu88 d56a5ae
Add docu (#1698)
mu88 c25f6a9
Use 'HaveXXError' pattern instead of 'BeXXError'
mu88 4bf5fd7
Use inline data for testing instead of generating test data within de…
mu88 85ffec9
Group tests by method and add more tests
mu88 f488b9b
Make test names more concise
mu88 d19c812
Protect against null values
mu88 fa30323
Update documentation
mu88 3f4a3ed
Add API files again
mu88 f4e223a
Improve null handling
mu88 75f36d2
Fix minor issues in docu and release notes
mu88 33c0b88
Improve some details like inheritance and null checks
mu88 328a937
Make System.Net.Http a conditional dependency for .NET 4.7
mu88 f181d8f
Fix merge conflicts
mu88 8e693b8
Revert "Fix merge conflicts"
mu88 6e8e760
Remove implicitly covered tests
mu88 44ad245
Update Src/FluentAssertions/Primitives/HttpResponseMessageAssertions.cs
mu88 421f1f6
Update Src/FluentAssertions/Primitives/HttpResponseMessageAssertions.cs
mu88 669f07d
Update docs/_pages/releases.md
mu88 a399935
Merge branch 'master' into feature/HttpResponseMessageAssertions
mu88 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
234 changes: 234 additions & 0 deletions
234
Src/FluentAssertions/Primitives/HttpResponseMessageAssertions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
using System.Diagnostics; | ||
using System.Net; | ||
using System.Net.Http; | ||
using FluentAssertions.Execution; | ||
|
||
namespace FluentAssertions.Primitives | ||
{ | ||
/// <summary> | ||
/// Contains a number of methods to assert that a <see cref="HttpResponseMessage"/> is in the expected state. | ||
/// </summary> | ||
[DebuggerNonUserCode] | ||
public class HttpResponseMessageAssertions : HttpResponseMessageAssertions<HttpResponseMessageAssertions> | ||
{ | ||
public HttpResponseMessageAssertions(HttpResponseMessage value) | ||
: base(value) | ||
{ | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Contains a number of methods to assert that a <see cref="HttpResponseMessage" /> is in the expected state. | ||
/// </summary> | ||
[DebuggerNonUserCode] | ||
public class HttpResponseMessageAssertions<TAssertions> : ObjectAssertions<HttpResponseMessage, TAssertions> | ||
where TAssertions : HttpResponseMessageAssertions<TAssertions> | ||
{ | ||
protected HttpResponseMessageAssertions(HttpResponseMessage value) | ||
: base(value) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is successful (2xx). | ||
/// </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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> BeSuccessful(string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be successful (2xx){reason}, but HttpResponseMessage was <null>."); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition(Subject!.IsSuccessStatusCode) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be successful (2xx){reason}, but found {0}.", Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is redirection (3xx). | ||
/// </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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> BeRedirection(string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be redirection (3xx){reason}, but HttpResponseMessage was <null>."); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition((int)Subject!.StatusCode is >= 300 and <= 399) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be redirection (3xx){reason}, but found {0}.", Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is either client (4xx) or server error (5xx). | ||
/// </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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> HaveError(string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be an error{reason}, but HttpResponseMessage was <null>."); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition(IsClientError() || IsServerError()) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be an error{reason}, but found {0}.", Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is client error (4xx). | ||
/// </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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> HaveClientError(string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be client error (4xx){reason}, but HttpResponseMessage was <null>."); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition(IsClientError()) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be client error (4xx){reason}, but found {0}.", Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is server error (5xx). | ||
/// </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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> HaveServerError(string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be server error (5xx){reason}, but HttpResponseMessage was <null>."); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition(IsServerError()) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be server error (5xx){reason}, but found {0}.", Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is equal to the specified <paramref name="expected"/> value. | ||
/// </summary> | ||
/// <param name="expected">The expected value</param> | ||
/// <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 <paramref name="because" />. | ||
/// </param> | ||
public AndConstraint<TAssertions> HaveStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be {0}{reason}, but HttpResponseMessage was <null>.", expected); | ||
|
||
if (success) | ||
mu88 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
Execute.Assertion | ||
.ForCondition(Subject!.StatusCode == expected) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode to be {0}{reason}, but found {1}.", expected, Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
/// <summary> | ||
/// Asserts that the <see cref="HttpStatusCode"/> is not equal to the specified <paramref name="unexpected"/> value. | ||
/// </summary> | ||
/// <param name="unexpected">The unexpected value</param> | ||
/// <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 <paramref name="because"/>. | ||
/// </param> | ||
public AndConstraint<TAssertions> NotHaveStatusCode(HttpStatusCode unexpected, string because = "", params object[] becauseArgs) | ||
{ | ||
var success = Execute.Assertion | ||
.ForCondition(Subject is not null) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode not to be {0}{reason}, but HttpResponseMessage was <null>.", unexpected); | ||
|
||
if (success) | ||
{ | ||
Execute.Assertion | ||
.ForCondition(Subject!.StatusCode != unexpected) | ||
.BecauseOf(because, becauseArgs) | ||
.FailWith("Expected HttpStatusCode not to be {0}{reason}, but found {1}.", unexpected, Subject.StatusCode); | ||
} | ||
|
||
return new AndConstraint<TAssertions>((TAssertions)this); | ||
} | ||
|
||
private bool IsServerError() => (int)Subject.StatusCode is >= 500 and <= 599; | ||
|
||
private bool IsClientError() => (int)Subject.StatusCode is >= 400 and <= 499; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.