Skip to content

Commit 04d53f3

Browse files
Crowbar90Francesco Venturoli
and
Francesco Venturoli
authored
feat(awesome-assertions): Added new project WireMock.Net.AwesomeAssertions (#1273)
* feat(awesome-assertions): Added new project WireMock.Net.AwesomeAssertions * feat(awesome-assertions): Applied dotnet naming convention for private readonly fields --------- Co-authored-by: Francesco Venturoli <[email protected]>
1 parent a8562fd commit 04d53f3

13 files changed

+757
-0
lines changed

‎WireMock.Net Solution.sln

+7
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TestWebApplica
128128
EndProject
129129
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Middleware.Tests", "test\WireMock.Net.Middleware.Tests\WireMock.Net.Middleware.Tests.csproj", "{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}"
130130
EndProject
131+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.AwesomeAssertions", "src\WireMock.Net.AwesomeAssertions\WireMock.Net.AwesomeAssertions.csproj", "{7753670F-7C7F-44BF-8BC7-08325588E60C}"
132+
EndProject
131133
Global
132134
GlobalSection(SolutionConfigurationPlatforms) = preSolution
133135
Debug|Any CPU = Debug|Any CPU
@@ -302,6 +304,10 @@ Global
302304
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
303305
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
304306
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.Build.0 = Release|Any CPU
307+
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
308+
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|Any CPU.Build.0 = Debug|Any CPU
309+
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|Any CPU.ActiveCfg = Release|Any CPU
310+
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|Any CPU.Build.0 = Release|Any CPU
305311
EndGlobalSection
306312
GlobalSection(SolutionProperties) = preSolution
307313
HideSolutionNode = FALSE
@@ -351,6 +357,7 @@ Global
351357
{B6269AAC-170A-4346-8B9A-579DED3D9A13} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
352358
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE} = {0BB8B634-407A-4610-A91F-11586990767A}
353359
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5} = {0BB8B634-407A-4610-A91F-11586990767A}
360+
{7753670F-7C7F-44BF-8BC7-08325588E60C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
354361
EndGlobalSection
355362
GlobalSection(ExtensibilityGlobals) = postSolution
356363
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright © WireMock.Net
2+
3+
using Stef.Validation;
4+
using WireMock.Server;
5+
6+
// ReSharper disable once CheckNamespace
7+
namespace WireMock.FluentAssertions;
8+
9+
/// <summary>
10+
/// Provides assertion methods to verify the number of calls made to a WireMock server.
11+
/// This class is used in the context of FluentAssertions.
12+
/// </summary>
13+
public class WireMockANumberOfCallsAssertions
14+
{
15+
private readonly IWireMockServer _server;
16+
private readonly int _callsCount;
17+
private readonly AssertionChain _chain;
18+
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="WireMockANumberOfCallsAssertions"/> class.
21+
/// </summary>
22+
/// <param name="server">The WireMock server to assert against.</param>
23+
/// <param name="callsCount">The expected number of calls to assert.</param>
24+
/// <param name="chain">The assertion chain</param>
25+
public WireMockANumberOfCallsAssertions(IWireMockServer server, int callsCount, AssertionChain chain)
26+
{
27+
_server = Guard.NotNull(server);
28+
_callsCount = callsCount;
29+
_chain = chain;
30+
}
31+
32+
/// <summary>
33+
/// Returns an instance of <see cref="WireMockAssertions"/> which can be used to assert the expected number of calls.
34+
/// </summary>
35+
/// <returns>A <see cref="WireMockAssertions"/> instance for asserting the number of calls to the server.</returns>
36+
public WireMockAssertions Calls()
37+
{
38+
return new WireMockAssertions(_server, _callsCount, _chain);
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright © WireMock.Net
2+
3+
using WireMock.Extensions;
4+
using WireMock.Matchers;
5+
6+
// ReSharper disable once CheckNamespace
7+
namespace WireMock.FluentAssertions;
8+
9+
#pragma warning disable CS1591
10+
public partial class WireMockAssertions
11+
{
12+
[CustomAssertion]
13+
public AndWhichConstraint<WireMockAssertions, string> AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
14+
{
15+
_ = AtAbsoluteUrl(new ExactMatcher(true, absoluteUrl), because, becauseArgs);
16+
17+
return new AndWhichConstraint<WireMockAssertions, string>(this, absoluteUrl);
18+
}
19+
20+
[CustomAssertion]
21+
public AndWhichConstraint<WireMockAssertions, IStringMatcher> AtAbsoluteUrl(IStringMatcher absoluteUrlMatcher, string because = "", params object[] becauseArgs)
22+
{
23+
var (filter, condition) = BuildFilterAndCondition(request => absoluteUrlMatcher.IsPerfectMatch(request.AbsoluteUrl));
24+
25+
var absoluteUrl = absoluteUrlMatcher.GetPatterns().FirstOrDefault().GetPattern();
26+
27+
_chain
28+
.BecauseOf(because, becauseArgs)
29+
.Given(() => RequestMessages)
30+
.ForCondition(requests => CallsCount == 0 || requests.Any())
31+
.FailWith(
32+
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but no calls were made.",
33+
absoluteUrl
34+
)
35+
.Then
36+
.ForCondition(condition)
37+
.FailWith(
38+
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but didn't find it among the calls to {1}.",
39+
_ => absoluteUrl,
40+
requests => requests.Select(request => request.AbsoluteUrl)
41+
);
42+
43+
FilterRequestMessages(filter);
44+
45+
return new AndWhichConstraint<WireMockAssertions, IStringMatcher>(this, absoluteUrlMatcher);
46+
}
47+
48+
[CustomAssertion]
49+
public AndWhichConstraint<WireMockAssertions, string> AtUrl(string url, string because = "", params object[] becauseArgs)
50+
{
51+
_ = AtUrl(new ExactMatcher(true, url), because, becauseArgs);
52+
53+
return new AndWhichConstraint<WireMockAssertions, string>(this, url);
54+
}
55+
56+
[CustomAssertion]
57+
public AndWhichConstraint<WireMockAssertions, IStringMatcher> AtUrl(IStringMatcher urlMatcher, string because = "", params object[] becauseArgs)
58+
{
59+
var (filter, condition) = BuildFilterAndCondition(request => urlMatcher.IsPerfectMatch(request.Url));
60+
61+
var url = urlMatcher.GetPatterns().FirstOrDefault().GetPattern();
62+
63+
_chain
64+
.BecauseOf(because, becauseArgs)
65+
.Given(() => RequestMessages)
66+
.ForCondition(requests => CallsCount == 0 || requests.Any())
67+
.FailWith(
68+
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
69+
url
70+
)
71+
.Then
72+
.ForCondition(condition)
73+
.FailWith(
74+
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.",
75+
_ => url,
76+
requests => requests.Select(request => request.Url)
77+
);
78+
79+
FilterRequestMessages(filter);
80+
81+
return new AndWhichConstraint<WireMockAssertions, IStringMatcher>(this, urlMatcher);
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright © WireMock.Net
2+
3+
#pragma warning disable CS1591
4+
using System;
5+
6+
// ReSharper disable once CheckNamespace
7+
namespace WireMock.FluentAssertions;
8+
9+
public partial class WireMockAssertions
10+
{
11+
[CustomAssertion]
12+
public AndWhichConstraint<WireMockAssertions, string> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
13+
{
14+
var (filter, condition) = BuildFilterAndCondition(request => string.Equals(request.ClientIP, clientIP, StringComparison.OrdinalIgnoreCase));
15+
16+
_chain
17+
.BecauseOf(because, becauseArgs)
18+
.Given(() => RequestMessages)
19+
.ForCondition(requests => CallsCount == 0 || requests.Any())
20+
.FailWith(
21+
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
22+
clientIP
23+
)
24+
.Then
25+
.ForCondition(condition)
26+
.FailWith(
27+
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
28+
_ => clientIP, requests => requests.Select(request => request.ClientIP)
29+
);
30+
31+
FilterRequestMessages(filter);
32+
33+
return new AndWhichConstraint<WireMockAssertions, string>(this, clientIP);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright © WireMock.Net
2+
3+
#pragma warning disable CS1591
4+
using System;
5+
using WireMock.Constants;
6+
7+
// ReSharper disable once CheckNamespace
8+
namespace WireMock.FluentAssertions;
9+
10+
public partial class WireMockAssertions
11+
{
12+
[CustomAssertion]
13+
public AndConstraint<WireMockAssertions> UsingConnect(string because = "", params object[] becauseArgs)
14+
=> UsingMethod(HttpRequestMethod.CONNECT, because, becauseArgs);
15+
16+
[CustomAssertion]
17+
public AndConstraint<WireMockAssertions> UsingDelete(string because = "", params object[] becauseArgs)
18+
=> UsingMethod(HttpRequestMethod.DELETE, because, becauseArgs);
19+
20+
[CustomAssertion]
21+
public AndConstraint<WireMockAssertions> UsingGet(string because = "", params object[] becauseArgs)
22+
=> UsingMethod(HttpRequestMethod.GET, because, becauseArgs);
23+
24+
[CustomAssertion]
25+
public AndConstraint<WireMockAssertions> UsingHead(string because = "", params object[] becauseArgs)
26+
=> UsingMethod(HttpRequestMethod.HEAD, because, becauseArgs);
27+
28+
[CustomAssertion]
29+
public AndConstraint<WireMockAssertions> UsingOptions(string because = "", params object[] becauseArgs)
30+
=> UsingMethod(HttpRequestMethod.OPTIONS, because, becauseArgs);
31+
32+
[CustomAssertion]
33+
public AndConstraint<WireMockAssertions> UsingPost(string because = "", params object[] becauseArgs)
34+
=> UsingMethod(HttpRequestMethod.POST, because, becauseArgs);
35+
36+
[CustomAssertion]
37+
public AndConstraint<WireMockAssertions> Using(string because = "", params object[] becauseArgs)
38+
=> UsingMethod(HttpRequestMethod., because, becauseArgs);
39+
40+
[CustomAssertion]
41+
public AndConstraint<WireMockAssertions> UsingPut(string because = "", params object[] becauseArgs)
42+
=> UsingMethod(HttpRequestMethod.PUT, because, becauseArgs);
43+
44+
[CustomAssertion]
45+
public AndConstraint<WireMockAssertions> UsingTrace(string because = "", params object[] becauseArgs)
46+
=> UsingMethod(HttpRequestMethod.TRACE, because, becauseArgs);
47+
48+
[CustomAssertion]
49+
public AndConstraint<WireMockAssertions> UsingAnyMethod(string because = "", params object[] becauseArgs)
50+
=> UsingMethod(Any, because, becauseArgs);
51+
52+
[CustomAssertion]
53+
public AndConstraint<WireMockAssertions> UsingMethod(string method, string because = "", params object[] becauseArgs)
54+
{
55+
var any = method == Any;
56+
Func<IRequestMessage, bool> predicate = request => (any && !string.IsNullOrEmpty(request.Method)) ||
57+
string.Equals(request.Method, method, StringComparison.OrdinalIgnoreCase);
58+
59+
var (filter, condition) = BuildFilterAndCondition(predicate);
60+
61+
_chain
62+
.BecauseOf(because, becauseArgs)
63+
.Given(() => RequestMessages)
64+
.ForCondition(requests => CallsCount == 0 || requests.Any())
65+
.FailWith(
66+
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but no calls were made.",
67+
method
68+
)
69+
.Then
70+
.ForCondition(condition)
71+
.FailWith(
72+
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but didn't find it among the methods {1}.",
73+
_ => method,
74+
requests => requests.Select(request => request.Method)
75+
);
76+
77+
FilterRequestMessages(filter);
78+
79+
return new AndConstraint<WireMockAssertions>(this);
80+
}
81+
}

0 commit comments

Comments
 (0)