Mockly 1.13.0

dotnet add package Mockly --version 1.13.0
                    
NuGet\Install-Package Mockly -Version 1.13.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Mockly" Version="1.13.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mockly" Version="1.13.0" />
                    
Directory.Packages.props
<PackageReference Include="Mockly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Mockly --version 1.13.0
                    
#r "nuget: Mockly, 1.13.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Mockly@1.13.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Mockly&version=1.13.0
                    
Install as a Cake Addin
#tool nuget:?package=Mockly&version=1.13.0
                    
Install as a Cake Tool

About

What's this?

Mockly is a powerful and flexible HTTP mocking library for .NET that makes it easy to test code that depends on HttpClient. It provides a fluent API for configuring HTTP request mocks, capturing request details, and asserting on HTTP interactions in your tests.

The library supports:

  • .NET Framework 4.7.2 and higher
  • .NET 8.0 and higher
  • FluentAssertions 7.x and 8.x integration for expressive test assertions

What's so special about that?

Unlike other HTTP mocking libraries, Mockly offers:

  • Fluent, intuitive API - Chain method calls to build complex mocking scenarios with ease
  • Wildcard pattern matching - Match URLs using wildcards (*) in paths and query strings
  • First-class header matching - Match request headers, bearer tokens, and content types directly
  • Custom matchers - Use predicates for advanced request matching logic
  • Request capture & inspection - Automatically capture all requests with full metadata (headers, body, timestamp)
  • Powerful assertions - Built-in FluentAssertions extensions for verifying HTTP behavior
  • Diagnostic support - Detailed error messages when unexpected requests occur
  • Extensibility - Design allows for custom response generators and matchers
  • Zero configuration - Works out of the box with sensible defaults
  • Performance optimized - Regex patterns are cached for efficient matching
  • Invocation limits - Restrict how many times a mock can respond using Once(), Twice(), or Times(n)
  • Response latency - Simulate slow endpoints with After(TimeSpan) to test timeout, cancellation and resilience

Who created this?

Mockly is created and maintained by Dennis Doomen, also the creator of FluentAssertions, PackageGuard, Reflectify, Pathy and the .NET Library Starter Kit. It's designed to work seamlessly with modern .NET testing practices and integrates naturally with FluentAssertions for expressive test assertions.

Key Features

🎯 Fluent Request Matching

mock.ForGet().WithPath("/api/users/*").RespondsWithJsonContent(user);
mock.ForPost().WithPath("/api/data").WithQuery("?filter=*").RespondsWithStatus(HttpStatusCode.Created);
mock.ForGet().WithPath("/api/secure").WithHeader("X-Api-Key").RespondsWithStatus(HttpStatusCode.OK);
mock.ForPost().WithPath("/api/auth").WithBearerToken("eyJ*").RespondsWithStatus(HttpStatusCode.OK);
mock.ForPost().WithPath("/api/json").WithContentType("application/json").RespondsWithStatus(HttpStatusCode.OK);

🏷️ Response Headers

Configure response headers such as Location, ETag or a custom Content-Type. Content headers are routed to the response content automatically; all other headers are added to the response headers.

mock.ForPost().WithPath("/api/users")
    .RespondsWithStatus(HttpStatusCode.Created)
    .WithHeader("Location", "/api/users/123")
    .WithHeader("ETag", "\"v1\"");

πŸ“ƒ Clear Reporting

When an unexpected request occurs and there are configured mocks, Mockly helps you diagnose by reporting the closest matching mock, broken down criterion by criterion (method, scheme/host, path, query, headers, body), so you can quickly see exactly what to adjust in your setup.

Unexpected request to:
  POST https://api.example.com/api/users

Closest matching mock:
  POST https://*/api/users
    method       βœ“ POST
    scheme/host  βœ“ api.example.com
    path         βœ“ /api/users
    query        βœ“ (none)
    header       βœ— expected "X-Tenant: acme" but the request had no such header
    body         βœ— expected property "role" to be "Admin" but found "User"

Registered mocks:
 - POST https://*/api/users where header "X-Tenant" matches "acme"

When the mismatch isn't on a single request, dump the whole conversation instead:

output.WriteLine(mock.GetTrafficReport());

πŸ” Request Capture & Inspection

var patches = new RequestCollection();
mock.ForPatch().WithPath("/api/update").CollectingRequestsIn(patches);

// After test execution
patches.Count.Should().Be(3);
patches.First().Path.Should().Contain("/api/update");

βœ… Powerful Assertions

mock.Should().HaveAllRequestsCalled();
mock.Requests.Should().NotBeEmpty();
mock.Requests.Should().NotContainUnexpectedCalls();

// Assert JSON-equivalence using a JSON string (ignores formatting/ordering)
mock.Requests.Should().ContainRequest()
    .WithBodyMatchingJson("{ \"id\": 1, \"name\": \"John\" }");

// Assert the body deserializes and is equivalent to an object graph
var expected = new { id = 1, name = "John" };

mock.Requests.Should().ContainRequestFor("https://api.example.com/*")
    .WithBodyEquivalentTo(expected);

🎨 Multiple Response Types

  • JSON content with automatic serialization
  • Test data builder integration via IResponseBuilder<T>
  • Raw string content
  • Custom HTTP status codes
  • Custom response generators
  • OData support

πŸ” Sequenced Responses

Configure a sequence of responses for the same matched request so consecutive calls get different responses (e.g. the classic "fail twice, then succeed" retry test). Chain ThenRespondsWith*(...) after any RespondsWith* method. The last response repeats for any calls beyond the configured sequence.

mock.ForGet().WithPath("/resource")
    .RespondsWithStatus(HttpStatusCode.ServiceUnavailable)
    .ThenRespondsWithStatus(HttpStatusCode.ServiceUnavailable)
    .ThenRespondsWithStatus(HttpStatusCode.OK);

The ThenRespondsWith* family mirrors the RespondsWith* methods (ThenRespondsWithJsonContent, ThenRespondsWithContent, ThenRespondsWithODataResult, and ThenRespondsWith(Func<RequestInfo, HttpResponseMessage>)).

πŸ” Auth & Rate-Limit Scenarios

Match basic auth credentials or API keys, and simulate the OAuth, token-refresh and rate-limiting flows that resilience libraries like Microsoft.Extensions.Http.Resilience are built to handle:

mock.ForGet("/api/secure").WithBasicAuth("user", "pass");
mock.ForGet("/api/secure").WithApiKey("X-Api-Key");

// OAuth token endpoint, with a correctly shaped token response
mock.ForPost("/token").RespondsWithOAuthToken("abc", expiresIn: TimeSpan.FromMinutes(5));

// The classic token-refresh test: first call 401, retry after refresh succeeds
mock.ForGet("/api/data").RespondsWithUnauthorizedThenSuccess("""{"value":42}""");

// 429 with a Retry-After header
mock.ForGet("/api/data").RespondsWithRateLimit(retryAfter: TimeSpan.FromSeconds(2));

πŸ›‘οΈ Fail-Fast Testing

mock.FailOnUnexpectedCalls = true; // Default behavior
// Throws UnexpectedRequestException if an unmocked request is made

πŸ“₯ Import From cURL

Bootstrap a mock from an existing curl command, such as the output of a browser's "Copy as cURL":

mock.ImportFromCurl("""
    curl -X POST https://api.example.com/users \
      -H 'Content-Type: application/json' \
      --data-raw '{"name":"mockly"}'
    """)
    .RespondsWithStatus(HttpStatusCode.Created);

The method (-X), URL, headers (-H) and body (-d/--data/--data-raw) are translated into the equivalent matching configuration. Importing HAR files is planned for a future release.

Quick Start

Install the package:

dotnet add package mockly

To get the assertions, also install one of the two assertion packages, depending on which version of FluentAssertions you're using:

dotnet add package FluentAssertions.Mockly.v7
dotnet add package FluentAssertions.Mockly.v8

Basic usage:

using Mockly;
using FluentAssertions;

// Arrange
var mock = new HttpMock();
mock.ForGet()
    .WithPath("/api/users/123")
    .RespondsWithJsonContent(new { Id = 123, Name = "John Doe" });

HttpClient client = mock.GetClient();

// Act
// Note: BaseAddress defaults to https://localhost/
var response = await client.GetAsync("/api/users/123");
var content = await response.Content.ReadAsStringAsync();

// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Contain("John Doe");
mock.Should().HaveAllRequestsCalled();

For complete documentation and advanced examples, visit mockly.org

This project ships an Agent Skill that helps AI Coding Agents use Mockly effectively. This file will be stored in the .agents/skills/mockly directory of your project when you build the project. You can disable this behavior by setting <MocklySkill>false</MocklySkill> in your project or Directory.Build.props.

Versioning

This library uses Semantic Versioning to give meaning to the version numbers. For the versions available, see the releases on this repository.

Credits

This library wouldn't have been possible without the following tools, packages and companies:

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Framework net472 is compatible.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Mockly:

Package Downloads
FluentAssertions.Mockly.v7

FluentAssertions extensions for Mockly.Http (compatible with FluentAssertions 7.x)

FluentAssertions.Mockly.v8

FluentAssertions extensions for Mockly (compatible with FluentAssertions 8.x)

Verify.Mockly

Adds Verify (https://github.com/VerifyTests/Verify) support for verifying Mockly (https://mockly.org/) types

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.13.0 202 9/27/2026
1.12.0 950 9/7/2026
1.11.0 760 8/16/2026
1.10.0 2,838 7/14/2026
1.9.0 291 7/5/2026
1.8.0 561 6/27/2026
1.7.1 1,153 6/2/2026
1.7.0 820 5/31/2026
1.6.0 282 5/23/2026
1.5.0 2,078 4/10/2026
1.4.1 701 3/31/2026
1.4.0 1,446 3/10/2026
1.3.0 489 2/19/2026
1.2.1 263 2/13/2026
1.2.0 261 2/8/2026
1.1.1 1,173 12/31/2025
1.1.0 264 12/22/2025
1.0.1 1,119 12/9/2025
1.0.0 429 12/8/2025
1.0.0-rc.6 215 12/7/2025
Loading failed