Don't mock HttpClient.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // ====================================================================== // Q: How do you unit test a class that uses HttpClient? // // Don't mock HttpClient. Give it a fake HttpMessageHandler: all of your own code // (serialization, headers, status codes) runs as normal. // Alternatively: WireMock.Net (a real HTTP server inside the test) for // integration tests of the client. // ====================================================================== public class StubHandler(HttpStatusCode status, string json) : HttpMessageHandler { public HttpRequestMessage? LastRequest { get; private set; } protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken ct) { LastRequest = request; return Task.FromResult(new HttpResponseMessage(status) { Content = new StringContent(json, Encoding.UTF8, "application/json") }); } } [Fact] public async Task Erp_422_becomes_ErpRejectedException() { var handler = new StubHandler(HttpStatusCode.UnprocessableEntity, """{"MESSAGE":"discontinued"}"""); var client = new ErpClient(new HttpClient(handler) { BaseAddress = new("http://erp/") }); await Assert.ThrowsAsync<ErpRejectedException>(() => client.SendOrderAsync(order, default)); Assert.True(handler.LastRequest!.Headers.Contains("Idempotency-Key")); } |