Skip to content

Commit 7b039e2

Browse files
committed
Added Assert for requests headers and their values.
1 parent 9c8762f commit 7b039e2

File tree

4 files changed

+256
-15
lines changed

4 files changed

+256
-15
lines changed

src/HttpClientTestHelpers/HttpRequestMessageAsserter.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@ public HttpRequestMessageAsserter With(Func<HttpRequestMessage, bool> requestFil
106106
/// <returns>The <seealso cref="HttpRequestMessageAsserter"/> for further assertions.</returns>
107107
public HttpRequestMessageAsserter WithUriPattern(string pattern)
108108
{
109-
if(string.IsNullOrEmpty(pattern))
109+
if (string.IsNullOrEmpty(pattern))
110110
{
111111
throw new ArgumentNullException(nameof(pattern));
112112
}
113113

114-
string condition = string.Empty;
114+
var condition = string.Empty;
115115
if (pattern != "*")
116116
{
117117
condition = $"uri pattern '{pattern}'";
@@ -141,12 +141,39 @@ public HttpRequestMessageAsserter WithHttpMethod(HttpMethod httpMethod)
141141
/// <returns>The <seealso cref="HttpRequestMessageAsserter"/> for further assertions.</returns>
142142
public HttpRequestMessageAsserter WithHttpVersion(Version httpVersion)
143143
{
144-
if(httpVersion == null)
144+
if (httpVersion == null)
145145
{
146146
throw new ArgumentNullException(nameof(httpVersion));
147147
}
148148

149149
return With(x => x.HasHttpVersion(httpVersion), $"HTTP Version '{httpVersion}'");
150150
}
151+
152+
/// <summary>
153+
/// Asserts wheter requests were made with a specific header name. Values are ignored.
154+
/// </summary>
155+
/// <param name="headerName">The name of the header that is expected.</param>
156+
/// <returns>The <seealso cref="HttpRequestMessageAsserter"/> for further assertions.</returns>
157+
public HttpRequestMessageAsserter WithHeader(string headerName)
158+
{
159+
if (string.IsNullOrEmpty(headerName))
160+
{
161+
throw new ArgumentNullException(nameof(headerName));
162+
}
163+
return With(x => x.HasHeader(headerName), $"header '{headerName}'");
164+
}
165+
166+
public HttpRequestMessageAsserter WithHeader(string headerName, string headerValue)
167+
{
168+
if (string.IsNullOrEmpty(headerName))
169+
{
170+
throw new ArgumentNullException(nameof(headerName));
171+
}
172+
if (string.IsNullOrEmpty(headerValue))
173+
{
174+
throw new ArgumentNullException(nameof(headerValue));
175+
}
176+
return With(x => x.HasHeader(headerName, headerValue), $"header '{headerName}' and value '{headerValue}'");
177+
}
151178
}
152179
}

src/HttpClientTestHelpers/HttpRequestMessageExtensions.cs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,36 +115,65 @@ public static bool HasHeader(this HttpRequestMessage httpRequestMessage, string
115115
}
116116

117117
/// <summary>
118-
/// Determines whether the request uri matches a pattern.
118+
/// Determines whether a specific header with a specific value is set on a request.
119119
/// </summary>
120120
/// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to check the correct method on.</param>
121-
/// <param name="pattern">A pattern to match with the request uri, support * as wildcards.</param>
122-
/// <returns>true when the request uri matches the pattern; otherwise, false.</returns>
123-
public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, string pattern)
121+
/// <param name="headerName">The name of the header to locate on the request.</param>
122+
/// <param name="headerValue">The value the header should have. Wildcard is supported.</param>
123+
/// <returns>true when the request contains a header with the specified name and value; otherwise, false.</returns>
124+
public static bool HasHeader(this HttpRequestMessage httpRequestMessage, string headerName, string headerValue)
124125
{
125126
if (httpRequestMessage == null)
126127
{
127128
throw new ArgumentNullException(nameof(httpRequestMessage));
128129
}
129130

130-
if (pattern == null)
131+
if (string.IsNullOrEmpty(headerName))
131132
{
132-
throw new ArgumentNullException(nameof(pattern));
133+
throw new ArgumentNullException(nameof(headerName));
133134
}
134135

135-
if (pattern == "*")
136+
if (string.IsNullOrEmpty(headerValue))
136137
{
137-
return true;
138+
throw new ArgumentNullException(nameof(headerValue));
138139
}
139140

140-
if (string.IsNullOrEmpty(pattern))
141+
if (httpRequestMessage.Headers.TryGetValues(headerName, out var values))
142+
{
143+
var value = string.Join(" ", values);
144+
return Matches(value, headerValue);
145+
}
146+
147+
return false;
148+
}
149+
150+
/// <summary>
151+
/// Determines whether the request uri matches a pattern.
152+
/// </summary>
153+
/// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to check the correct method on.</param>
154+
/// <param name="pattern">A pattern to match with the request uri, support * as wildcards.</param>
155+
/// <returns>true when the request uri matches the pattern; otherwise, false.</returns>
156+
public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, string pattern)
157+
{
158+
if (httpRequestMessage == null)
141159
{
142-
return false;
160+
throw new ArgumentNullException(nameof(httpRequestMessage));
143161
}
144162

163+
return pattern switch
164+
{
165+
null => throw new ArgumentNullException(nameof(pattern)),
166+
"" => false,
167+
"*" => true,
168+
_ => Matches(httpRequestMessage.RequestUri.AbsoluteUri, pattern),
169+
};
170+
}
171+
172+
private static bool Matches(string value, string pattern)
173+
{
145174
var regex = Regex.Escape(pattern).Replace("\\*", "(.*)");
146175

147-
return Regex.IsMatch(httpRequestMessage.RequestUri.AbsoluteUri, regex);
176+
return Regex.IsMatch(value, regex);
148177
}
149178
}
150179
}

test/HttpClientTestHelpers.Tests/HttpRequestMessageAsserterTests.cs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,137 @@ public void WithHttpVersion_RequestsWithCorrectVersion_ReturnsHttpRequestMessage
148148

149149
var result = sut.WithHttpVersion(HttpVersion.Version11);
150150

151+
Assert.NotNull(result);
152+
Assert.IsType<HttpRequestMessageAsserter>(result);
153+
}
154+
155+
#nullable disable
156+
[Theory]
157+
[InlineData(null)]
158+
[InlineData("")]
159+
public void WithHeader_NullOrEmptyHeaderName_ThrowsArgumentNullException(string headerName)
160+
{
161+
var sut = new HttpRequestMessageAsserter(Enumerable.Empty<HttpRequestMessage>());
162+
163+
var exception = Assert.Throws<ArgumentNullException>(() => sut.WithHeader(headerName));
164+
165+
Assert.Equal("headerName", exception.ParamName);
166+
}
167+
#nullable restore
168+
169+
[Fact]
170+
public void WithHeader_NoRequests_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
171+
{
172+
var sut = new HttpRequestMessageAsserter(Enumerable.Empty<HttpRequestMessage>());
173+
174+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("api-version"));
175+
176+
Assert.Equal("Expected at least one request to be made with header 'api-version', but no requests were made.", exception.Message);
177+
}
178+
179+
[Fact]
180+
public void WithHeader_NoMatchingRequests_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
181+
{
182+
var sut = new HttpRequestMessageAsserter(new[] { new HttpRequestMessage() });
183+
184+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("api-version"));
185+
186+
Assert.Equal("Expected at least one request to be made with header 'api-version', but no requests were made.", exception.Message);
187+
}
188+
189+
[Fact]
190+
public void WithHeader_MatchingRequest_ReturnsHttpRequestMessageAsserter()
191+
{
192+
var request = new HttpRequestMessage();
193+
request.Headers.Add("api-version", "1.0");
194+
var sut = new HttpRequestMessageAsserter(new[] { request });
195+
196+
var result = sut.WithHeader("api-version");
197+
198+
Assert.NotNull(result);
199+
Assert.IsType<HttpRequestMessageAsserter>(result);
200+
}
201+
202+
#nullable disable
203+
[Theory]
204+
[InlineData(null)]
205+
[InlineData("")]
206+
public void WithHeaderNameAndValue_NullOrEmptyHeaderName_ThrowsArgumentNullException(string headerName)
207+
{
208+
var sut = new HttpRequestMessageAsserter(Enumerable.Empty<HttpRequestMessage>());
209+
210+
var exception = Assert.Throws<ArgumentNullException>(() => sut.WithHeader(headerName, "someValue"));
211+
212+
Assert.Equal("headerName", exception.ParamName);
213+
}
214+
215+
[Theory]
216+
[InlineData(null)]
217+
[InlineData("")]
218+
public void WithHeaderNameAndValue_NullOrEmptyValue_ThrowsArgumentNullException(string headerValue)
219+
{
220+
var sut = new HttpRequestMessageAsserter(Enumerable.Empty<HttpRequestMessage>());
221+
222+
var exception = Assert.Throws<ArgumentNullException>(() => sut.WithHeader("someHeader", headerValue));
223+
224+
Assert.Equal("headerValue", exception.ParamName);
225+
}
226+
#nullable restore
227+
228+
[Fact]
229+
public void WithHeaderNameAndValue_NoRequests_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
230+
{
231+
var sut = new HttpRequestMessageAsserter(Enumerable.Empty<HttpRequestMessage>());
232+
233+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("someHeader", "someValue"));
234+
235+
Assert.Equal("Expected at least one request to be made with header 'someHeader' and value 'someValue', but no requests were made.", exception.Message);
236+
}
237+
238+
[Fact]
239+
public void WithHeaderNameAndValue_RequestWithoutHeaders_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
240+
{
241+
var request = new HttpRequestMessage();
242+
var sut = new HttpRequestMessageAsserter(new[] { request });
243+
244+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("api-version", "1.0"));
245+
246+
Assert.Equal("Expected at least one request to be made with header 'api-version' and value '1.0', but no requests were made.", exception.Message);
247+
}
248+
249+
[Fact]
250+
public void WithHeaderNameAndValue_RequestWithNotMatchingHeaderName_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
251+
{
252+
var request = new HttpRequestMessage();
253+
request.Headers.Add("no-api-version", "1.0");
254+
var sut = new HttpRequestMessageAsserter(new[] { request });
255+
256+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("api-version", "1.0"));
257+
258+
Assert.Equal("Expected at least one request to be made with header 'api-version' and value '1.0', but no requests were made.", exception.Message);
259+
}
260+
261+
[Fact]
262+
public void WithHeaderNameAndValue_RequestWithNotMatchingHeaderValue_ThrowsHttpRequestMessageAssertionExceptionWithSpecificMessage()
263+
{
264+
var request = new HttpRequestMessage();
265+
request.Headers.Add("api-version", "unknown");
266+
var sut = new HttpRequestMessageAsserter(new[] { request });
267+
268+
var exception = Assert.Throws<HttpRequestMessageAssertionException>(() => sut.WithHeader("api-version", "1.0"));
269+
270+
Assert.Equal("Expected at least one request to be made with header 'api-version' and value '1.0', but no requests were made.", exception.Message);
271+
}
272+
273+
[Fact]
274+
public void WithHeaderNameAndValue_RequestWithMatchinHeader_ReturnsHttpRequestMessageAssert()
275+
{
276+
var request = new HttpRequestMessage();
277+
request.Headers.Add("api-version", "1.0");
278+
var sut = new HttpRequestMessageAsserter(new[] { request });
279+
280+
var result = sut.WithHeader("api-version", "1.0");
281+
151282
Assert.NotNull(result);
152283
Assert.IsType<HttpRequestMessageAsserter>(result);
153284
}

test/HttpClientTestHelpers.Tests/HttpRequestMessageExtensionsTests.HasHeader.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ public void HasHeader_NullHeaderName_ThrowsArgumentNullException(string headerNa
2727
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasHeader(headerName));
2828
Assert.Equal("headerName", exception.ParamName);
2929
}
30+
31+
[Fact]
32+
public void HasHeader_NullRequestNonNullHeaderNameAndNonNullHeaderValue_ThrowsArgumentNullException()
33+
{
34+
HttpRequestMessage sut = null;
35+
36+
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasHeader("host", "value"));
37+
Assert.Equal("httpRequestMessage", exception.ParamName);
38+
}
39+
40+
[Theory]
41+
[InlineData(null)]
42+
[InlineData("")]
43+
public void HasHeader_NullHeaderNameAndNonNullHeaderValue_ThrowsArgumentNullException(string headerName)
44+
{
45+
using var sut = new HttpRequestMessage();
46+
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasHeader(headerName, "value"));
47+
Assert.Equal("headerName", exception.ParamName);
48+
}
49+
50+
[Theory]
51+
[InlineData(null)]
52+
[InlineData("")]
53+
public void HasHeader_NonNullHeaderNameAndNullHeaderValue_ThrowsArgumentNullException(string headerValue)
54+
{
55+
using var sut = new HttpRequestMessage();
56+
var exception = Assert.Throws<ArgumentNullException>(() => sut.HasHeader("Host", headerValue));
57+
Assert.Equal("headerValue", exception.ParamName);
58+
}
3059
#nullable restore
3160

3261
[Fact]
@@ -37,13 +66,38 @@ public void HasHeader_ExistingHeaderName_ReturnsTrue()
3766

3867
Assert.True(sut.HasHeader("Host"));
3968
}
40-
69+
4170
[Fact]
4271
public void HasHeader_NotExistingHeaderName_ReturnsFalse()
4372
{
4473
using var sut = new HttpRequestMessage();
4574

4675
Assert.False(sut.HasHeader("Host"));
4776
}
77+
78+
[Theory]
79+
[InlineData("example.com")]
80+
[InlineData("example*")]
81+
[InlineData("*.com")]
82+
[InlineData("*")]
83+
public void HasHeader_ExistingHeaderNameMatchingValue_ReturnsTrue(string value)
84+
{
85+
using var sut = new HttpRequestMessage();
86+
sut.Headers.Host = "example.com";
87+
88+
Assert.True(sut.HasHeader("Host", value));
89+
}
90+
91+
[Theory]
92+
[InlineData("example.com")]
93+
[InlineData("example*")]
94+
[InlineData("*.com")]
95+
public void HasHeader_ExistingHeaderNameNotMatchingValue_ReturnsFalse(string value)
96+
{
97+
using var sut = new HttpRequestMessage();
98+
sut.Headers.Host = "myhost.net";
99+
100+
Assert.False(sut.HasHeader("Host", value));
101+
}
48102
}
49103
}

0 commit comments

Comments
 (0)