Tools

Mockly: fluent HTTP mocking for .NET tests that call HttpClient

Dennis Doomen released Mockly, an open-source library that makes testing code which calls HttpClient much simpler. It replaces hand-written HttpMessageHandler subclasses and fragile Moq setups on the protected SendAsync method. Its main strength is that failure paths such as retries, timeouts, 401 refreshes and 429 throttling can be simulated in a line or two, and unmatched requests produce a clear explanation.

Dennis Doomen Dennis Doomen
Published
Reading time
16 min read
agent run #13
agent run #13
Go to original dennisdoomen.com

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Install mockly plus FluentAssertions.Mockly.v8 or v7, depending on your Fluent Assertions version
  • Use GetClient(), GetClientFactory() or GetMessageHandler() to fit HttpClient, IHttpClientFactory or custom handler setups
  • Chain ThenRespondsWithStatus() to model retries; the last response in the chain keeps being returned
  • Use ThrowsException<HttpRequestException>() or TimesOut() to simulate network failures; the request is still recorded
  • RespondsWithRateLimit() and RespondsWithUnauthorizedThenSuccess() help verify resilience and token refresh logic
  • FailOnUnexpectedCalls is true by default, so forgotten mocks fail loudly with UnexpectedRequestException

Mockly is a new open-source library for mocking HTTP calls in .NET tests, built by Dennis Doomen after he found no existing tool that fit his testing style. Instead of subclassing HttpMessageHandler or overriding SendAsync with magic strings, you create an HttpMock, describe the expected requests fluently and ask it for an HttpClient, an IHttpClientFactory or a raw message handler. Requests can be matched on method, URL wildcards, query parameters, headers, bearer tokens, form fields and bodies, including JSON comparison.

The library focuses on the unhappy paths that often stay untested. You can chain responses for retry scenarios, limit a mock with Once() or Times(n), delay responses to test timeouts, and throw network-level exceptions. OAuth token responses, 401-then-success refresh flows and 429 rate limits have dedicated helpers. Unexpected requests throw by default and explain which closest mock failed and on which criterion.

Real-world use

  • Unit testing a service class that calls a payment or CRM API without making real network calls
  • Verifying Polly or Microsoft.Extensions.Http.Resilience retry policies against 503 and 429 responses
  • Testing a token refresh flow where the first call returns 401 and the retry succeeds
  • Turning a curl command copied from browser developer tools into a test setup in one step

Why it matters

Failure paths such as timeouts, retries, token refresh and throttling can now be covered by short, readable tests instead of hand-built fakes. Clear mismatch messages also shorten the time spent diagnosing failing tests.

This summary was generated by the agent from the original post on Dennis Doomen. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message