diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs index 65dc27130..87380bc8c 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockANumberOfCallsAssertions.cs @@ -4,11 +4,11 @@ using WireMock.Server; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; /// /// Provides assertion methods to verify the number of calls made to a WireMock server. -/// This class is used in the context of FluentAssertions. +/// This class is used in the context of AwesomeAssertions. /// public class WireMockANumberOfCallsAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs new file mode 100644 index 000000000..a830e9668 --- /dev/null +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtPath.cs @@ -0,0 +1,83 @@ +// Copyright © WireMock.Net + +using WireMock.Extensions; +using WireMock.Matchers; + +// ReSharper disable once CheckNamespace +namespace WireMock.AwesomeAssertions; + +#pragma warning disable CS1591 +public partial class WireMockAssertions +{ + [CustomAssertion] + public AndWhichConstraint AtAbsolutePath(string absolutePath, string because = "", params object[] becauseArgs) + { + _ = AtAbsolutePath(new ExactMatcher(true, absolutePath), because, becauseArgs); + + return new AndWhichConstraint(this, absolutePath); + } + + [CustomAssertion] + public AndWhichConstraint AtAbsolutePath(IStringMatcher absolutePathMatcher, string because = "", params object[] becauseArgs) + { + var (filter, condition) = BuildFilterAndCondition(request => absolutePathMatcher.IsPerfectMatch(request.AbsolutePath)); + + var absolutePath = absolutePathMatcher.GetPatterns().FirstOrDefault().GetPattern(); + + _chain + .BecauseOf(because, becauseArgs) + .Given(() => RequestMessages) + .ForCondition(requests => CallsCount == 0 || requests.Any()) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but no calls were made.", + absolutePath + ) + .Then + .ForCondition(condition) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but didn't find it among the calls to {1}.", + _ => absolutePath, + requests => requests.Select(request => request.AbsolutePath) + ); + + FilterRequestMessages(filter); + + return new AndWhichConstraint(this, absolutePathMatcher); + } + + [CustomAssertion] + public AndWhichConstraint AtPath(string path, string because = "", params object[] becauseArgs) + { + _ = AtPath(new ExactMatcher(true, path), because, becauseArgs); + + return new AndWhichConstraint(this, path); + } + + [CustomAssertion] + public AndWhichConstraint AtPath(IStringMatcher pathMatcher, string because = "", params object[] becauseArgs) + { + var (filter, condition) = BuildFilterAndCondition(request => pathMatcher.IsPerfectMatch(request.Path)); + + var path = pathMatcher.GetPatterns().FirstOrDefault().GetPattern(); + + _chain + .BecauseOf(because, becauseArgs) + .Given(() => RequestMessages) + .ForCondition(requests => CallsCount == 0 || requests.Any()) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but no calls were made.", + path + ) + .Then + .ForCondition(condition) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but didn't find it among the calls to {1}.", + _ => path, + requests => requests.Select(request => request.Path) + ); + + FilterRequestMessages(filter); + + return new AndWhichConstraint(this, pathMatcher); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs index 87d8fb0f8..562716cb8 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.AtUrl.cs @@ -4,7 +4,7 @@ using WireMock.Matchers; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; #pragma warning disable CS1591 public partial class WireMockAssertions diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs index 9c0977ed8..6e2684726 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.FromClientIP.cs @@ -4,7 +4,7 @@ using System; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs index 62301d31a..e3ce6c12b 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.UsingMethod.cs @@ -5,7 +5,7 @@ using WireMock.Constants; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs index bdd04a42e..c6fd9c5fa 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithBody.cs @@ -11,7 +11,7 @@ using WireMock.Models; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs index d56427593..8293cd9d9 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithHeader.cs @@ -3,7 +3,7 @@ #pragma warning disable CS1591 // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs index 6d51b3fdf..704b23317 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.WithProxy.cs @@ -4,7 +4,7 @@ using System; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs index ca7a41942..e24a38410 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockAssertions.cs @@ -7,7 +7,7 @@ using WireMock.Server; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; public partial class WireMockAssertions { diff --git a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs index 260a1a943..184be0e95 100644 --- a/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs +++ b/src/WireMock.Net.AwesomeAssertions/Assertions/WireMockReceivedAssertions.cs @@ -4,7 +4,7 @@ using WireMock.Server; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions; +namespace WireMock.AwesomeAssertions; /// /// Contains a number of methods to assert that the is in the expected state. diff --git a/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs b/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs index 73e2eac76..95d6fc711 100644 --- a/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs +++ b/src/WireMock.Net.AwesomeAssertions/Extensions/WireMockExtensions.cs @@ -3,7 +3,7 @@ using WireMock.Server; // ReSharper disable once CheckNamespace -namespace WireMock.FluentAssertions +namespace WireMock.AwesomeAssertions { /// /// Contains extension methods for custom assertions in unit tests. diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs new file mode 100644 index 000000000..c54eb9638 --- /dev/null +++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.AtPath.cs @@ -0,0 +1,83 @@ +// Copyright © WireMock.Net + +using WireMock.Extensions; +using WireMock.Matchers; + +// ReSharper disable once CheckNamespace +namespace WireMock.FluentAssertions; + +#pragma warning disable CS1591 +public partial class WireMockAssertions +{ + [CustomAssertion] + public AndWhichConstraint AtAbsolutePath(string absolutePath, string because = "", params object[] becauseArgs) + { + _ = AtAbsolutePath(new ExactMatcher(true, absolutePath), because, becauseArgs); + + return new AndWhichConstraint(this, absolutePath); + } + + [CustomAssertion] + public AndWhichConstraint AtAbsolutePath(IStringMatcher absolutePathMatcher, string because = "", params object[] becauseArgs) + { + var (filter, condition) = BuildFilterAndCondition(request => absolutePathMatcher.IsPerfectMatch(request.AbsolutePath)); + + var absolutePath = absolutePathMatcher.GetPatterns().FirstOrDefault().GetPattern(); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => RequestMessages) + .ForCondition(requests => CallsCount == 0 || requests.Any()) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but no calls were made.", + absolutePath + ) + .Then + .ForCondition(condition) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the absolute path {0}{reason}, but didn't find it among the calls to {1}.", + _ => absolutePath, + requests => requests.Select(request => request.AbsolutePath) + ); + + FilterRequestMessages(filter); + + return new AndWhichConstraint(this, absolutePathMatcher); + } + + [CustomAssertion] + public AndWhichConstraint AtPath(string path, string because = "", params object[] becauseArgs) + { + _ = AtPath(new ExactMatcher(true, path), because, becauseArgs); + + return new AndWhichConstraint(this, path); + } + + [CustomAssertion] + public AndWhichConstraint AtPath(IStringMatcher pathMatcher, string because = "", params object[] becauseArgs) + { + var (filter, condition) = BuildFilterAndCondition(request => pathMatcher.IsPerfectMatch(request.Path)); + + var path = pathMatcher.GetPatterns().FirstOrDefault().GetPattern(); + + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => RequestMessages) + .ForCondition(requests => CallsCount == 0 || requests.Any()) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but no calls were made.", + path + ) + .Then + .ForCondition(condition) + .FailWith( + "Expected {context:wiremockserver} to have been called at address matching the path {0}{reason}, but didn't find it among the calls to {1}.", + _ => path, + requests => requests.Select(request => request.Path) + ); + + FilterRequestMessages(filter); + + return new AndWhichConstraint(this, pathMatcher); + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs b/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs index fecd784ed..6b152f08f 100644 --- a/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs +++ b/test/WireMock.Net.Tests/FluentAssertions/WireMockAssertionsTests.cs @@ -108,7 +108,7 @@ public async Task HaveReceivedACall_AtAbsoluteUrl_WhenACallWasMadeToAbsoluteUrl_ } [Fact] - public async Task HaveReceivedACall_AtAbsoluteUrlWilcardMAtcher_WhenACallWasMadeToAbsoluteUrl_Should_BeOK() + public async Task HaveReceivedACall_AtAbsoluteUrlWildcardMatcher_WhenACallWasMadeToAbsoluteUrl_Should_BeOK() { await _httpClient.GetAsync("anyurl").ConfigureAwait(false); @@ -143,6 +143,106 @@ public async Task HaveReceivedACall_AtAbsoluteUrl_Should_ThrowWhenNoCallsMatchin .WithMessage($"Expected _server to have been called at address matching the absolute url \"anyurl\", but didn't find it among the calls to {{\"http://localhost:{_portUsed}/\"}}."); } + [Fact] + public async Task HaveReceivedNoCalls_AtAbsolutePath_WhenACallWasNotMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("xxx").ConfigureAwait(false); + + _server.Should() + .HaveReceivedNoCalls() + .AtAbsolutePath("anypath"); + } + + [Fact] + public async Task HaveReceived0Calls_AtAbsolutePath_WhenACallWasNotMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("xxx").ConfigureAwait(false); + + _server.Should() + .HaveReceived(0).Calls() + .AtAbsolutePath("anypath"); + } + + [Fact] + public async Task HaveReceived1Calls_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("anypath").ConfigureAwait(false); + + _server.Should() + .HaveReceived(1).Calls() + .AtAbsolutePath("/anypath"); + } + + [Fact] + public async Task HaveReceived1Calls_AtAbsolutePathUsingPost_WhenAPostCallWasMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.PostAsync("anypath", new StringContent("")).ConfigureAwait(false); + + _server.Should() + .HaveReceived(1).Calls() + .AtAbsolutePath("/anypath") + .And + .UsingPost(); + } + + [Fact] + public async Task HaveReceived2Calls_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("anypath").ConfigureAwait(false); + + await _httpClient.GetAsync("anypath").ConfigureAwait(false); + + _server.Should() + .HaveReceived(2).Calls() + .AtAbsolutePath("/anypath"); + } + + [Fact] + public async Task HaveReceivedACall_AtAbsolutePath_WhenACallWasMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("anypath").ConfigureAwait(false); + + _server.Should() + .HaveReceivedACall() + .AtAbsolutePath(new WildcardMatcher("/any*")); + } + + [Fact] + public async Task HaveReceivedACall_AtAbsolutePathWildcardMatcher_WhenACallWasMadeToAbsolutePath_Should_BeOK() + { + await _httpClient.GetAsync("anypath").ConfigureAwait(false); + + _server.Should() + .HaveReceivedACall() + .AtAbsolutePath("/anypath"); + } + + [Fact] + public void HaveReceivedACall_AtAbsolutePath_Should_ThrowWhenNoCallsWereMade() + { + Action act = () => _server.Should() + .HaveReceivedACall() + .AtAbsolutePath("anypath"); + + act.Should() + .Throw() + .WithMessage("Expected _server to have been called at address matching the absolute path \"anypath\", but no calls were made."); + } + + [Fact] + public async Task HaveReceivedACall_AtAbsolutePath_Should_ThrowWhenNoCallsMatchingTheAbsolutePathWereMade() + { + await _httpClient.GetAsync("").ConfigureAwait(false); + + Action act = () => _server.Should() + .HaveReceivedACall() + .AtAbsolutePath("/anypath"); + + act.Should() + .Throw() + .WithMessage($"Expected _server to have been called at address matching the absolute path \"/anypath\", but didn't find it among the calls to {{\"/\"}}."); + } + [Fact] public async Task HaveReceivedACall_WithHeader_WhenACallWasMadeWithExpectedHeader_Should_BeOK() {