In this lesson, you will learn how to isolate your HttpClient logic by intercepting outgoing requests without ever hitting the actual network.
The Challenge of Testing HttpClient
When your code uses HttpClient, it relies on the HttpMessageHandler to process requests. If you use a real client in your unit tests, you risk flaky tests due to network latency, downtime, or rate limiting. Instead of letting the request reach the wire, we can "trap" the request at the handler level and return a canned response.
Mocking the Protected SendAsync
The HttpMessageHandler is an abstract class, but its primary execution method, SendAsync, is protected. To test it, you need to mock this protected member so you can dictate exactly what the client receives back.
Using a framework like Moq, you can set up an expectation for SendAsync to return a HttpResponseMessage of your choosing:
var handlerMock = new Mock<HttpMessageHandler>();
handlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("{\"data\": \"success\"}")
});
// Inject this mock into your HttpClient
var httpClient = new HttpClient(handlerMock.Object);
Why this is powerful
By injecting this httpClient into your service, you gain full control over the environment. You can simulate success (200 OK), client errors (400 Bad Request), or even server timeouts (500 Internal Server Error) instantly.
Because we are mocking the handler rather than the HttpClient itself, you don't need to wrap the client in an interface. You are testing the real HttpClient behavior—including its headers and message processing—while replacing only the physical transport layer. This keeps your tests fast, deterministic, and entirely offline, satisfying the requirements for reliable unit testing in the 15th phase of our curriculum.
Key Takeaway: By mocking the protected SendAsync method of HttpMessageHandler, you gain absolute control over the HttpClient response pipeline without the unpredictability of real network calls.