Skip to content

Commit 39a0abb

Browse files
committed
Adds basic TestableHttpMessageHandler.
1 parent 958b601 commit 39a0abb

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using System.Net;
5+
using System.Net.Http;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace HttpClientTestHelpers
10+
{
11+
/// <summary>
12+
/// A testable HTTP message handler that captures all requests and always returns the same response.
13+
/// </summary>
14+
public class TestableHttpMessageHandler : HttpMessageHandler
15+
{
16+
private readonly ConcurrentQueue<HttpRequestMessage> httpRequestMessages = new ConcurrentQueue<HttpRequestMessage>();
17+
private HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
18+
19+
/// <summary>
20+
/// Gets the collection of captured requests made using this HttpMessageHandler.
21+
/// </summary>
22+
public IEnumerable<HttpRequestMessage> Requests => httpRequestMessages;
23+
24+
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
25+
{
26+
httpRequestMessages.Enqueue(request);
27+
return Task.FromResult(response);
28+
}
29+
30+
/// <summary>
31+
/// Configure the <see cref="HttpResponseMessage"/> that should be returned for each request.
32+
/// </summary>
33+
/// <param name="httpResponseMessage"></param>
34+
public void RespondWith(HttpResponseMessage httpResponseMessage)
35+
{
36+
response = httpResponseMessage ?? throw new ArgumentNullException(nameof(httpResponseMessage));
37+
}
38+
}
39+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[*.cs]
22
# CA1707: Identifiers should not contain underscores
33
dotnet_diagnostic.CA1707.severity = none
4+
5+
# CA2007: Consider calling ConfigureAwait on the awaited task
6+
dotnet_diagnostic.CA2007.severity = silent
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Net;
3+
using System.Net.Http;
4+
using System.Threading.Tasks;
5+
6+
using Xunit;
7+
8+
namespace HttpClientTestHelpers.Tests
9+
{
10+
public class TestableHttpMessageHandlerTests
11+
{
12+
[Fact]
13+
public async Task SendAsync_WhenRequestsAreMade_LogsRequests()
14+
{
15+
using var sut = new TestableHttpMessageHandler();
16+
using var client = new HttpClient(sut);
17+
using var request = new HttpRequestMessage(HttpMethod.Get, "https://example.com");
18+
19+
_ = await client.SendAsync(request);
20+
21+
Assert.Contains(request, sut.Requests);
22+
}
23+
24+
[Fact]
25+
public async Task SendAsync_WhenMultipleRequestsAreMade_AllRequestsAreLogged()
26+
{
27+
using var sut = new TestableHttpMessageHandler();
28+
using var client = new HttpClient(sut);
29+
using var request1 = new HttpRequestMessage(HttpMethod.Get, "https://example1.com");
30+
using var request2 = new HttpRequestMessage(HttpMethod.Post, "https://example2.com");
31+
using var request3 = new HttpRequestMessage(HttpMethod.Delete, "https://example3.com");
32+
using var request4 = new HttpRequestMessage(HttpMethod.Head, "https://example4.com");
33+
34+
_ = await client.SendAsync(request1);
35+
_ = await client.SendAsync(request2);
36+
_ = await client.SendAsync(request3);
37+
_ = await client.SendAsync(request4);
38+
39+
Assert.Equal(new[] { request1, request2, request3, request4 }, sut.Requests);
40+
}
41+
42+
[Fact]
43+
public async Task SendAsync_ByDefault_ReturnsHttpStatusCodeOK()
44+
{
45+
using var sut = new TestableHttpMessageHandler();
46+
using var client = new HttpClient(sut);
47+
48+
var result = await client.GetAsync(new Uri("https://example.com"));
49+
50+
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
51+
}
52+
53+
[Fact]
54+
public async Task SendAsync_WhenRespondWithIsSet_SetRespondIsUsed()
55+
{
56+
using var sut = new TestableHttpMessageHandler();
57+
using var response = new HttpResponseMessage(HttpStatusCode.NotFound);
58+
sut.RespondWith(response);
59+
using var client = new HttpClient(sut);
60+
61+
var result = await client.GetAsync(new Uri("https://example.com"));
62+
63+
Assert.Equal(HttpStatusCode.NotFound, result.StatusCode);
64+
Assert.Same(response, result);
65+
}
66+
67+
#nullable disable
68+
[Fact]
69+
public void RespondWith_NullValue_ThrowsArgumentNullException()
70+
{
71+
using var sut = new TestableHttpMessageHandler();
72+
var exception = Assert.Throws<ArgumentNullException>(() => sut.RespondWith(null));
73+
Assert.Equal("httpResponseMessage", exception.ParamName);
74+
}
75+
#nullable restore
76+
}
77+
}

0 commit comments

Comments
 (0)