|
5 | 5 | <br> |
6 | 6 | </h1> |
7 | 7 |
|
8 | | - |
9 | | -<h4 align="center">Fluent HTTP mocking for .NET like it should have been done</h4> |
10 | | - |
| 8 | +<h4 align="center">FluentAssertions extensions for Mockly</h4> |
11 | 9 |
|
12 | 10 | <div align="center"> |
13 | 11 |
|
14 | 12 | [](https://github.com/dennisdoomen/fluentassertions.mockly/actions?query=branch%3Amain) |
15 | 13 | [](https://coveralls.io/github/dennisdoomen/fluentassertions.mockly?branch=main) |
16 | 14 | [](https://github.com/dennisdoomen/fluentassertions.mockly/releases/latest) |
17 | | -[](https://www.nuget.org/packages/mockly) |
18 | | -[](https://libraries.io/nuget/mockly) |
| 15 | +[](https://www.nuget.org/packages/FluentAssertions.Mockly.v7) |
| 16 | +[](https://www.nuget.org/packages/FluentAssertions.Mockly.v8) |
19 | 17 |  |
20 | | -[](https://github.com/dennisdoomen/fluentassertions.mockly/graphs/contributors) |
21 | | -[](https://github.com/dennisdoomen/fluentassertions.mockly) |
22 | | -[](https://github.com/dennisdoomen/fluentassertions.mockly/graphs/commit-activity) |
23 | 18 | [](https://github.com/dennisdoomen/fluentassertions.mockly/issues) |
24 | 19 |  |
25 | | -[](https://makeapullrequest.com) |
26 | | - |
27 | 20 |
|
28 | 21 | </div> |
29 | 22 |
|
30 | | -## 📚 [Documentation](https://dennisdoomen.github.io/mockly/) |
31 | | - |
32 | | -**Visit the [official documentation website](https://dennisdoomen.github.io/mockly/)** for comprehensive guides, API reference, and examples. |
33 | | - |
34 | | -- [Quick Start](https://dennisdoomen.github.io/mockly/docs/quick-start) - Get started in 5 minutes |
35 | | -- [Usage Guide](https://dennisdoomen.github.io/mockly/docs/usage) - Learn core features |
36 | | -- [Advanced Features](https://dennisdoomen.github.io/mockly/docs/advanced) - Custom matchers, assertions, and more |
37 | | -- [Building](https://dennisdoomen.github.io/mockly/docs/building) - Build from source |
38 | | -- [Contributing](https://dennisdoomen.github.io/mockly/docs/contributing) - Contribution guidelines |
39 | | - |
40 | | -## About |
41 | | - |
42 | | -### What's this? |
43 | | - |
44 | | -**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. |
45 | | - |
46 | | -The library supports: |
47 | | -* **.NET Framework 4.7.2** and higher |
48 | | -* **.NET 8.0** and higher |
49 | | -* **FluentAssertions 7.x and 8.x** integration for expressive test assertions |
50 | | - |
51 | | -### What's so special about that? |
52 | | - |
53 | | -Unlike other HTTP mocking libraries, Mockly offers: |
54 | | - |
55 | | -* **Fluent, intuitive API** - Chain method calls to build complex mocking scenarios with ease |
56 | | -* **Wildcard pattern matching** - Match URLs using wildcards (`*`) in paths and query strings |
57 | | -* **Custom matchers** - Use predicates for advanced request matching logic |
58 | | -* **Request capture & inspection** - Automatically capture all requests with full metadata (headers, body, timestamp) |
59 | | -* **Powerful assertions** - Built-in FluentAssertions extensions for verifying HTTP behavior |
60 | | -* **Diagnostic support** - Detailed error messages when unexpected requests occur |
61 | | -* **Extensibility** - Design allows for custom response generators and matchers |
62 | | -* **Zero configuration** - Works out of the box with sensible defaults |
63 | | -* **Performance optimized** - Regex patterns are cached for efficient matching |
64 | | -* **Invocation limits** - Restrict how many times a mock can respond using `Once()`, `Twice()`, or `Times(n)` |
65 | | - |
66 | | -### Who created this? |
67 | | - |
68 | | -Mockly is created and maintained by [Dennis Doomen](https://github.com/dennisdoomen), also the creator of [FluentAssertions](https://fluentassertions.com/), [PackageGuard](https://github.com/dennisdoomen/packageguard), [Reflectify](https://github.com/dennisdoomen/reflectify), [Pathy](https://github.com/dennisdoomen/pathy) and the [.NET Library Starter Kit](https://github.com/dennisdoomen/dotnet-library-starter-kit). It's designed to work seamlessly with modern .NET testing practices and integrates naturally with FluentAssertions for expressive test assertions. |
69 | | - |
70 | | -## Key Features |
71 | | - |
72 | | -### 🎯 Fluent Request Matching |
73 | | - |
74 | | -```csharp |
75 | | -mock.ForGet().WithPath("/api/users/*").RespondsWithJsonContent(user); |
76 | | -mock.ForPost().WithPath("/api/data").WithQuery("?filter=*").RespondsWithStatus(HttpStatusCode.Created); |
77 | | -``` |
78 | | - |
79 | | -### 📃 Clear Reporting |
80 | | - |
81 | | -When an unexpected request occurs and there are configured mocks, Mockly helps you diagnose by reporting the closest matching mock (method, scheme/host/path/query) so you can quickly see what to adjust in your setup. |
82 | | - |
83 | | -``` |
84 | | -Unexpected request to: |
85 | | - GET http://localhost/fnv_collectiveschemes(111) |
86 | | -
|
87 | | -Closest matching mock: |
88 | | - GET https://*/fnv_collectiveschemes(123*) |
89 | | -
|
90 | | -Registered mocks: |
91 | | - - GET https://*/fnv_collectiveschemes |
92 | | - - POST https://*/fnv_collectiveschemes |
93 | | - - GET https://*/fnv_collectiveschemes(123*) |
94 | | - - GET https://*/fnv_collectiveschemes(123*) (1 custom matcher(s)) where (request => request.Uri?.Query == "?$count=1") |
95 | | - - GET https://*/fnv_collectiveschemes(456) |
96 | | -``` |
97 | | - |
98 | | -### 🔍 Request Capture & Inspection |
99 | | - |
100 | | -```csharp |
101 | | -var patches = new RequestCollection(); |
102 | | -mock.ForPatch().WithPath("/api/update").CollectingRequestIn(patches); |
103 | | - |
104 | | -// After test execution |
105 | | -patches.Count.Should().Be(3); |
106 | | -patches.First().Path.Should().Contain("/api/update"); |
107 | | -``` |
108 | | - |
109 | | -### ✅ Powerful Assertions |
110 | | - |
111 | | -```csharp |
112 | | -mock.Should().HaveAllRequestsCalled(); |
113 | | -mock.Requests.Should().NotBeEmpty(); |
114 | | -mock.Requests.Should().NotContainUnexpectedCalls(); |
| 23 | +## Documentation |
115 | 24 |
|
116 | | -// Assert JSON-equivalence using a JSON string (ignores formatting/ordering) |
117 | | -mock.Requests.Should().ContainRequest() |
118 | | - .WithBodyMatchingJson("{ \"id\": 1, \"name\": \"x\" }"); |
| 25 | +Mockly documentation (including assertion usage) lives on **https://mockly.org**. |
119 | 26 |
|
120 | | -// Assert the body deserializes and is equivalent to an object graph |
121 | | -var expected = new { id = 1, name = "x" }; |
122 | | - |
123 | | -mock.Requests.Should().ContainRequestForUrl("http://localhost:7021/api/*") |
124 | | - .WithBodyEquivalentTo(expected); |
125 | | -``` |
| 27 | +This repository contains **only the FluentAssertions assertion packages** for Mockly. |
| 28 | +For the core HTTP mocking library, see: |
126 | 29 |
|
127 | | -### 🎨 Multiple Response Types |
| 30 | +- Website: https://mockly.org |
| 31 | +- Core repo: https://github.com/dennisdoomen/mockly |
| 32 | +- Core NuGet package: https://www.nuget.org/packages/Mockly |
128 | 33 |
|
129 | | -* JSON content with automatic serialization |
130 | | -* Test data builder integration via `IResponseBuilder<T>` |
131 | | -* Raw string content |
132 | | -* Custom HTTP status codes |
133 | | -* Custom response generators |
134 | | -* OData support |
| 34 | +## Packages |
135 | 35 |
|
136 | | -### 🛡️ Fail-Fast Testing |
| 36 | +Choose the package that matches your FluentAssertions major version: |
137 | 37 |
|
138 | | -```csharp |
139 | | -mock.FailOnUnexpectedCalls = true; // Default behavior |
140 | | -// Throws UnexpectedRequestException if an unmocked request is made |
141 | | -``` |
| 38 | +| Package | FluentAssertions | NuGet | |
| 39 | +| --- | --- | --- | |
| 40 | +| `FluentAssertions.Mockly.v7` | 7.x | https://www.nuget.org/packages/FluentAssertions.Mockly.v7 | |
| 41 | +| `FluentAssertions.Mockly.v8` | 8.x | https://www.nuget.org/packages/FluentAssertions.Mockly.v8 | |
142 | 42 |
|
143 | | -## Quick Start |
| 43 | +## Quick start |
144 | 44 |
|
145 | | -Install the package: |
| 45 | +Install Mockly and the assertion package you need: |
146 | 46 |
|
147 | 47 | ```bash |
148 | | -dotnet add package mockly |
149 | | -``` |
150 | | - |
151 | | -To get the assertions, also install one of the two assertion packages, depending on which version of FluentAssertions you're using: |
| 48 | +dotnet add package Mockly |
152 | 49 |
|
153 | | -```bash |
| 50 | +# Pick one: |
154 | 51 | dotnet add package FluentAssertions.Mockly.v7 |
155 | 52 | dotnet add package FluentAssertions.Mockly.v8 |
156 | 53 | ``` |
157 | 54 |
|
158 | | -Basic usage: |
| 55 | +Example: |
159 | 56 |
|
160 | 57 | ```csharp |
161 | | -using Mockly; |
| 58 | +using System.Net; |
162 | 59 | using FluentAssertions; |
| 60 | +using Mockly; |
163 | 61 |
|
164 | | -// Arrange |
165 | 62 | var mock = new HttpMock(); |
166 | 63 | mock.ForGet() |
167 | 64 | .WithPath("/api/users/123") |
168 | | - .RespondsWithJsonContent(new { Id = 123, Name = "John Doe" }); |
169 | | - |
170 | | -HttpClient client = mock.GetClient(); |
| 65 | + .RespondsWithStatus(HttpStatusCode.OK); |
171 | 66 |
|
172 | | -// Act |
173 | | -// Note: BaseAddress defaults to https://localhost/ |
| 67 | +var client = mock.GetClient(); |
174 | 68 | var response = await client.GetAsync("/api/users/123"); |
175 | | -var content = await response.Content.ReadAsStringAsync(); |
176 | 69 |
|
177 | | -// Assert |
178 | 70 | response.StatusCode.Should().Be(HttpStatusCode.OK); |
179 | | -content.Should().Contain("John Doe"); |
180 | 71 | mock.Should().HaveAllRequestsCalled(); |
181 | 72 | ``` |
182 | 73 |
|
183 | | -**For complete documentation and advanced examples, visit [dennisdoomen.github.io/mockly](https://dennisdoomen.github.io/mockly/)** |
184 | | - |
185 | 74 | ## Building |
186 | 75 |
|
187 | | -To build this repository locally, you need: |
188 | | -* The [.NET SDKs](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) for .NET 4.7 and 8.0. |
189 | | -* Visual Studio, JetBrains Rider or Visual Studio Code with the C# DevKit |
190 | | - |
191 | | -Build using PowerShell: |
192 | | - |
193 | 76 | ```bash |
194 | 77 | ./build.ps1 |
195 | 78 | ``` |
196 | 79 |
|
197 | | -Or with the [Nuke tool](https://nuke.build/docs/getting-started/installation/): |
198 | | - |
199 | | -```bash |
200 | | -nuke |
201 | | -``` |
202 | | - |
203 | | -For more details, see the [Building documentation](https://dennisdoomen.github.io/mockly/docs/building). |
204 | | - |
205 | 80 | ## Contributing |
206 | 81 |
|
207 | | -Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. |
208 | | - |
209 | | -For detailed contribution information, visit the [Contributing documentation](https://dennisdoomen.github.io/mockly/docs/contributing). |
210 | | - |
211 | | -Previous contributors: |
212 | | - |
213 | | -<a href="https://github.com/dennisdoomen/fluentassertions.mockly/graphs/contributors"> |
214 | | - <img src="https://contrib.rocks/image?repo=dennisdoomen/fluentassertions.mockly" alt="contrib.rocks image" /> |
215 | | -</a> |
216 | | - |
217 | | -(Made with [contrib.rocks](https://contrib.rocks)) |
| 82 | +Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) and open an issue or PR. |
218 | 83 |
|
219 | 84 | ## Versioning |
220 | 85 |
|
221 | | -This library uses [Semantic Versioning](https://semver.org/) to give meaning to the version numbers. For the versions available, see the [releases](https://github.com/dennisdoomen/fluentassertions.mockly/releases) on this repository. |
222 | | - |
223 | | -## Credits |
224 | | - |
225 | | -This library wouldn't have been possible without the following tools, packages and companies: |
226 | | - |
227 | | -* [FluentAssertions](https://fluentassertions.com/) - Fluent API for asserting the results of unit tests by [Dennis Doomen](https://github.com/dennisdoomen) |
228 | | -* [Nuke](https://nuke.build/) - Smart automation for DevOps teams and CI/CD pipelines by [Matthias Koch](https://github.com/matkoch) |
229 | | -* [xUnit](https://xunit.net/) - Community-focused unit testing tool for .NET by [Brad Wilson](https://github.com/bradwilson) |
230 | | -* [Coverlet](https://github.com/coverlet-coverage/coverlet) - Cross platform code coverage for .NET by [Toni Solarin-Sodara](https://github.com/tonerdo) |
231 | | -* [GitVersion](https://gitversion.net/) - From git log to SemVer in no time |
232 | | -* [ReportGenerator](https://reportgenerator.io/) - Converts coverage reports by [Daniel Palme](https://github.com/danielpalme) |
233 | | -* [StyleCopyAnalyzer](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) - StyleCop rules for .NET |
234 | | -* [Roslynator](https://github.com/dotnet/roslynator) - A set of code analysis tools for C# by [Josef Pihrt](https://github.com/josefpihrt) |
235 | | -* [CSharpCodingGuidelines](https://github.com/bkoelman/CSharpGuidelinesAnalyzer) - Roslyn analyzers by [Bart Koelman](https://github.com/bkoelman) to go with the [C# Coding Guidelines](https://csharpcodingguidelines.com/) |
236 | | -* [Meziantou](https://github.com/meziantou/Meziantou.Framework) - Another set of awesome Roslyn analyzers by [Gérald Barré](https://github.com/meziantou) |
237 | | - |
238 | | -## Related Projects |
239 | | - |
240 | | -You may also be interested in: |
241 | | - |
242 | | -* [FluentAssertions](https://fluentassertions.com/) - The assertion library that Mockly integrates with |
243 | | -* [PackageGuard](https://github.com/dennisdoomen/packageguard) - Get a grip on your open-source packages |
244 | | -* [Reflectify](https://github.com/dennisdoomen/reflectify) - Reflection extensions without causing dependency pains |
245 | | -* [Pathy](https://github.com/dennisdoomen/pathy) - Fluently building and using file and directory paths without binary dependencies |
246 | | -* [.NET Library Starter Kit](https://github.com/dennisdoomen/dotnet-library-starter-kit) - A battle-tested starter kit for building open-source and internal NuGet libraries |
| 86 | +This repository uses [Semantic Versioning](https://semver.org/). See the [releases](https://github.com/dennisdoomen/fluentassertions.mockly/releases). |
247 | 87 |
|
248 | 88 | ## License |
249 | 89 |
|
|
0 commit comments