Skip to content

Commit af82680

Browse files
committed
Fix FluentAssertions on Header(s)
1 parent a7b0d50 commit af82680

File tree

3 files changed

+257
-149
lines changed

3 files changed

+257
-149
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#pragma warning disable CS1591
2+
using System.Collections.Generic;
3+
using WireMock.Types;
4+
5+
// ReSharper disable once CheckNamespace
6+
namespace WireMock.FluentAssertions;
7+
8+
public partial class WireMockAssertions
9+
{
10+
[CustomAssertion]
11+
public AndConstraint<WireMockAssertions> WitHeaderKey(string expectedKey, string because = "", params object[] becauseArgs)
12+
{
13+
var (filter, condition) = BuildFilterAndCondition(request =>
14+
{
15+
return request.Headers?.Any(h => h.Key == expectedKey) == true;
16+
});
17+
18+
Execute.Assertion
19+
.BecauseOf(because, becauseArgs)
20+
.Given(() => _requestMessages)
21+
.ForCondition(requests => _callsCount == 0 || requests.Any())
22+
.FailWith(
23+
"Expected {context:wiremockserver} to have been called with Header {0}{reason}.",
24+
expectedKey
25+
)
26+
.Then
27+
.ForCondition(condition)
28+
.FailWith(
29+
"Expected {context:wiremockserver} to have been called with Header {0}{reason}, but didn't find it among the calls with Header(s) {1}.",
30+
_ => expectedKey,
31+
requests => requests.Select(request => request.Headers)
32+
);
33+
34+
_requestMessages = filter(_requestMessages).ToList();
35+
36+
return new AndConstraint<WireMockAssertions>(this);
37+
}
38+
39+
[CustomAssertion]
40+
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs)
41+
=> WithHeader(expectedKey, new[] { value }, because, becauseArgs);
42+
43+
[CustomAssertion]
44+
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
45+
{
46+
var (filter, condition) = BuildFilterAndCondition(request =>
47+
{
48+
var headers = request.Headers?.ToArray() ?? new KeyValuePair<string, WireMockList<string>>[0];
49+
50+
var matchingHeaderValues = headers.Where(h => h.Key == expectedKey).SelectMany(h => h.Value.ToArray()).ToArray();
51+
52+
if (expectedValues.Length == 1 && matchingHeaderValues.Length == 1)
53+
{
54+
return matchingHeaderValues[0] == expectedValues[0];
55+
}
56+
57+
var trimmedHeaderValues = string.Join(",", matchingHeaderValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToArray();
58+
return expectedValues.Any(trimmedHeaderValues.Contains);
59+
});
60+
61+
Execute.Assertion
62+
.BecauseOf(because, becauseArgs)
63+
.Given(() => _requestMessages)
64+
.ForCondition(requests => _callsCount == 0 || requests.Any())
65+
.FailWith(
66+
"Expected {context:wiremockserver} to have been called with Header {0} and Values {1}{reason}.",
67+
expectedKey,
68+
expectedValues
69+
)
70+
.Then
71+
.ForCondition(condition)
72+
.FailWith(
73+
"Expected {context:wiremockserver} to have been called with Header {0} and Values {1}{reason}, but didn't find it among the calls with Header(s) {2}.",
74+
_ => expectedKey,
75+
_ => expectedValues,
76+
requests => requests.Select(request => request.Headers)
77+
);
78+
79+
_requestMessages = filter(_requestMessages).ToList();
80+
81+
return new AndConstraint<WireMockAssertions>(this);
82+
}
83+
84+
[CustomAssertion]
85+
public AndConstraint<WireMockAssertions> WithoutHeaderKey(string unexpectedKey, string because = "", params object[] becauseArgs)
86+
{
87+
var (filter, condition) = BuildFilterAndCondition(request =>
88+
{
89+
return request.Headers?.Any(h => h.Key == unexpectedKey) != true;
90+
});
91+
92+
Execute.Assertion
93+
.BecauseOf(because, becauseArgs)
94+
.Given(() => _requestMessages)
95+
.ForCondition(requests => _callsCount == 0 || requests.Any())
96+
.FailWith(
97+
"Expected {context:wiremockserver} not to have been called with Header {0}{reason}.",
98+
unexpectedKey
99+
)
100+
.Then
101+
.ForCondition(condition)
102+
.FailWith(
103+
"Expected {context:wiremockserver} not to have been called with Header {0}{reason}, but found it among the calls with Header(s) {1}.",
104+
_ => unexpectedKey,
105+
requests => requests.Select(request => request.Headers)
106+
);
107+
108+
_requestMessages = filter(_requestMessages).ToList();
109+
110+
return new AndConstraint<WireMockAssertions>(this);
111+
}
112+
113+
[CustomAssertion]
114+
public AndConstraint<WireMockAssertions> WithoutHeader(string unexpectedKey, string value, string because = "", params object[] becauseArgs)
115+
=> WithoutHeader(unexpectedKey, new[] { value }, because, becauseArgs);
116+
117+
[CustomAssertion]
118+
public AndConstraint<WireMockAssertions> WithoutHeader(string unexpectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
119+
{
120+
var (filter, condition) = BuildFilterAndCondition(request =>
121+
{
122+
var headers = request.Headers?.ToArray() ?? new KeyValuePair<string, WireMockList<string>>[0];
123+
124+
var matchingHeaderValues = headers.Where(h => h.Key == unexpectedKey).SelectMany(h => h.Value.ToArray()).ToArray();
125+
126+
if (expectedValues.Length == 1 && matchingHeaderValues.Length == 1)
127+
{
128+
return matchingHeaderValues[0] != expectedValues[0];
129+
}
130+
131+
var trimmedHeaderValues = string.Join(",", matchingHeaderValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToArray();
132+
return !expectedValues.Any(trimmedHeaderValues.Contains);
133+
});
134+
135+
Execute.Assertion
136+
.BecauseOf(because, becauseArgs)
137+
.Given(() => _requestMessages)
138+
.ForCondition(requests => _callsCount == 0 || requests.Any())
139+
.FailWith(
140+
"Expected {context:wiremockserver} not to have been called with Header {0} and Values {1}{reason}.",
141+
unexpectedKey,
142+
expectedValues
143+
)
144+
.Then
145+
.ForCondition(condition)
146+
.FailWith(
147+
"Expected {context:wiremockserver} not to have been called with Header {0} and Values {1}{reason}, but found it among the calls with Header(s) {2}.",
148+
_ => unexpectedKey,
149+
_ => expectedValues,
150+
requests => requests.Select(request => request.Headers)
151+
);
152+
153+
_requestMessages = filter(_requestMessages).ToList();
154+
155+
return new AndConstraint<WireMockAssertions>(this);
156+
}
157+
}

src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs

+5-82
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Collections.Generic;
44
using WireMock.Matchers;
55
using WireMock.Server;
6-
using WireMock.Types;
76

87
// ReSharper disable once CheckNamespace
98
namespace WireMock.FluentAssertions;
@@ -13,13 +12,13 @@ public partial class WireMockAssertions
1312
private const string Any = "*";
1413
private readonly int? _callsCount;
1514
private IReadOnlyList<IRequestMessage> _requestMessages;
16-
private readonly IReadOnlyList<KeyValuePair<string, WireMockList<string>>> _headers;
15+
//private readonly IReadOnlyList<KeyValuePair<string, WireMockList<string>>> _headers;
1716

1817
public WireMockAssertions(IWireMockServer subject, int? callsCount)
1918
{
2019
_callsCount = callsCount;
2120
_requestMessages = subject.LogEntries.Select(logEntry => logEntry.RequestMessage).ToList();
22-
_headers = _requestMessages.SelectMany(req => req.Headers).ToList();
21+
// _headers = _requestMessages.SelectMany(req => req.Headers).ToList();
2322
}
2423

2524
[CustomAssertion]
@@ -39,7 +38,8 @@ public AndWhichConstraint<WireMockAssertions, string> AtAbsoluteUrl(string absol
3938
.ForCondition(condition)
4039
.FailWith(
4140
"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}.",
42-
_ => absoluteUrl, requests => requests.Select(request => request.AbsoluteUrl)
41+
_ => absoluteUrl,
42+
requests => requests.Select(request => request.AbsoluteUrl)
4343
);
4444

4545
_requestMessages = filter(_requestMessages).ToList();
@@ -124,84 +124,7 @@ public AndWhichConstraint<WireMockAssertions, string> FromClientIP(string client
124124
return new AndWhichConstraint<WireMockAssertions, string>(this, clientIP);
125125
}
126126

127-
[CustomAssertion]
128-
public AndConstraint<WireMockAssertions> WitHeaderKey(string expectedKey, string because = "", params object[] becauseArgs)
129-
{
130-
using (new AssertionScope("headers from requests sent"))
131-
{
132-
_headers.Select(h => h.Key).Should().Contain(expectedKey, because, becauseArgs);
133-
}
134-
135-
return new AndConstraint<WireMockAssertions>(this);
136-
}
137-
138-
[CustomAssertion]
139-
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs)
140-
=> WithHeader(expectedKey, new[] { value }, because, becauseArgs);
141-
142-
[CustomAssertion]
143-
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
144-
{
145-
using (new AssertionScope($"header \"{expectedKey}\" from requests sent with value(s)"))
146-
{
147-
var matchingHeaderValues = _headers.Where(h => h.Key == expectedKey).SelectMany(h => h.Value.ToArray())
148-
.ToArray();
149-
150-
if (expectedValues.Length == 1)
151-
{
152-
matchingHeaderValues.Should().Contain(expectedValues.First(), because, becauseArgs);
153-
}
154-
else
155-
{
156-
var trimmedHeaderValues = string.Join(",", matchingHeaderValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToList();
157-
foreach (var expectedValue in expectedValues)
158-
{
159-
trimmedHeaderValues.Should().Contain(expectedValue, because, becauseArgs);
160-
}
161-
}
162-
}
163-
164-
return new AndConstraint<WireMockAssertions>(this);
165-
}
166-
167-
[CustomAssertion]
168-
public AndConstraint<WireMockAssertions> WithoutHeaderKey(string unexpectedKey, string because = "", params object[] becauseArgs)
169-
{
170-
using (new AssertionScope("headers from requests sent"))
171-
{
172-
_headers.Select(h => h.Key).Should().NotContain(unexpectedKey, because, becauseArgs);
173-
}
174-
175-
return new AndConstraint<WireMockAssertions>(this);
176-
}
177-
178-
[CustomAssertion]
179-
public AndConstraint<WireMockAssertions> WithoutHeader(string unexpectedKey, string value, string because = "", params object[] becauseArgs)
180-
=> WithoutHeader(unexpectedKey, new[] { value }, because, becauseArgs);
181-
182-
[CustomAssertion]
183-
public AndConstraint<WireMockAssertions> WithoutHeader(string unexpectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
184-
{
185-
using (new AssertionScope($"header \"{unexpectedKey}\" from requests sent with value(s)"))
186-
{
187-
var matchingHeaderValues = _headers.Where(h => h.Key == unexpectedKey).SelectMany(h => h.Value.ToArray()).ToArray();
188-
189-
if (expectedValues.Length == 1)
190-
{
191-
matchingHeaderValues.Should().NotContain(expectedValues.First(), because, becauseArgs);
192-
}
193-
else
194-
{
195-
var trimmedHeaderValues = string.Join(",", matchingHeaderValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToList();
196-
foreach (var expectedValue in expectedValues)
197-
{
198-
trimmedHeaderValues.Should().NotContain(expectedValue, because, becauseArgs);
199-
}
200-
}
201-
}
202-
203-
return new AndConstraint<WireMockAssertions>(this);
204-
}
127+
205128

206129
private (Func<IReadOnlyList<IRequestMessage>, IReadOnlyList<IRequestMessage>> Filter, Func<IReadOnlyList<IRequestMessage>, bool> Condition) BuildFilterAndCondition(Func<IRequestMessage, bool> predicate)
207130
{

0 commit comments

Comments
 (0)