mockly
/mockly
Pisze testy w .NET z biblioteką Mockly, która mockuje żądania HttpClient, dopasowuje nagłówki i sprawdza interakcje HTTP.
- Autor
- dennisdoomen ↗
- Repozytorium
- mockly ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 26.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 23
- Skrypty
- 5
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 5
Brak sygnałów. Repozytorium zmienione 26.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
- 5 skryptów w paczce. Przejrzyj je przed instalacją, bo Claude może je uruchomić.
Skrypty: AcceptApiChanges.ps1, AcceptApiChanges.sh, build.cmd, build.ps1, build.sh
Co robi i kiedy
Pisze testy w .NET z biblioteką Mockly, która mockuje żądania HttpClient, dopasowuje nagłówki i sprawdza interakcje HTTP.
Oryginalny opis (EN)
Helps write tests using Mockly — a fluent HTTP mocking library for .NET that intercepts HttpClient calls. Use this skill when writing unit or integration tests that need to mock HTTP requests, configure responses (status codes, JSON, OData, raw content), match headers, capture and inspect requests, limit mock invocations, or assert HTTP interactions with FluentAssertions.
Jak działa
- Setup
- HTTP Verbs
- URL Matching
- Request Body Matching
- Header Matching
- Responses
- Request Capture
- Invocation Limits
- Response Latency
- Reset / Clear
Podgląd SKILL.md
---
name: mockly
description: >
Helps write tests using Mockly — a fluent HTTP mocking library for .NET that intercepts HttpClient
calls. Use this skill when writing unit or integration tests that need to mock HTTP requests,
configure responses (status codes, JSON, OData, raw content), match headers, capture and inspect requests,
limit mock invocations, or assert HTTP interactions with FluentAssertions.
---
# Mockly
Fluent HTTP mocking library for .NET. Intercepts `HttpClient` calls via a custom `HttpMessageHandler`.
Unmatched requests throw `UnexpectedRequestException` by default (`FailOnUnexpectedCalls = true`).
Default base address: `https://localhost/`.
## Setup
```csharp
var mock = new HttpMock();
mock.ForGet().WithPath("/api/users").RespondsWithStatus(HttpStatusCode.OK);
HttpClient client = mock.GetClient(); // or mock.GetClientFactory()
```
## HTTP Verbs
```csharp
// Convenience methods per verb (each also has a "(urlPattern)" overload)
mock.ForGet();
mock.ForPost();
mock.ForPut();
mock.ForPatch();
mock.ForDelete();
mock.ForHead();
mock.ForOptions();
// Generic entry point for any (including non-standard) verb
mock.For(HttpMethod.Get).WithPath("/api/data").RespondsWithStatus(HttpStatusCode.OK);
mock.For(new HttpMethod("PROPFIND"), "https://localhost/dav/*").RespondsWithStatus(HttpStatusCode.OK);
```
## URL Matching
```csharp
// Exact path (leading slash optional); * is wildcard; {name} is a named route placeholder
mock.ForGet().WithPath("/api/users/*").RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().WithPath("/api/users/{id}").RespondsWithJsonContent(req => new { Id = req.RouteValue("id") });
// Query: omitting WithQuery() rejects requests that include a query string
mock.ForGet().WithPath("/api/search").WithQuery("?q=*").RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().WithPath("/api/search").WithAnyQuery().RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().WithPath("/api/search").WithoutQuery().RespondsWithStatus(HttpStatusCode.OK);
// Scheme / host
mock.ForGet().ForHttps().ForHost("api.example.com").WithPath("/data").RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().ForHttp().ForAnyHost().WithPath("/data").RespondsWithStatus(HttpStatusCode.OK);
// Full-URL shorthand (scheme + host + path + query, all support *)
mock.ForGet("https://api.example.com/users/*?q=*").RespondsWithStatus(HttpStatusCode.OK);
mock.ForPatch("http://*.example.com/*").RespondsWithStatus(HttpStatusCode.OK);
```
## Request Body Matching
```csharp
mock.ForPost().WithPath("/api/data").WithBody("*keyword*").RespondsWithStatus(HttpStatusCode.NoContent);
mock.ForPost().WithPath("/api/data").WithBody(new { name = "John" }).RespondsWithStatus(HttpStatusCode.NoContent); // JSON object
mock.ForPost().WithPath("/api/data").WithBodyMatchingJson("{\"name\":\"John\"}").RespondsWithStatus(HttpStatusCode.NoContent);
mock.ForPost().WithPath("/api/data").WithBodyMatchingRegex(".*keyword.*").RespondsWithStatus(HttpStatusCode.NoContent);
// Custom predicate (sync or async) — use .With() for custom body or URI checks
mock.ForPost().WithPath("/api/data").With(req => req.Body!.Contains("keyword")).RespondsWithStatus(HttpStatusCode.NoContent);
// Body matching (WithBody, WithBodyMatchingJson, etc.) only works when the Content-Type is recognized as
// textual (text/*, multipart/*, application/json, application/xml, and similar). For an unrecognized or
// binary-looking Content-Type that is actually text, opt in with TreatBodyAsTextual():
mock.ForPost().WithPath("/api/data").WithBody("*keyword*").TreatBodyAsTextual().RespondsWithStatus(HttpStatusCode.NoContent);
```
## Header Matching
```csharp
mock.ForGet().WithPath("/api/secure").WithHeader("X-API-Key").RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().WithPath("/api/secure").WithHeader("X-Trace-Id", "abc-*").RespondsWithStatus(HttpStatusCode.OK);
mock.ForGet().WithPath("/api/auth").WithBearerToken().RespondsWithStatus(HttpStatusCode.OK);
mock.ForPost().WithPath("/api/json").WithContentType("application/json").RespondsWithStatus(HttpStatusCode.OK);
```
## Responses
```csharp
mock.ForDelete().WithPath("/api/items/1").RespondsWithStatus(HttpStatusCode.NoContent);
mock.ForGet().WithPath("/api/user").RespondsWithJsonContent(new { Id = 1, Name = "Alice" });
mock.ForGet().WithPath("/api/user").RespondsWithJsonContent(HttpStatusCode.Created, new { Id = 1 });
mock.ForGet().WithPath("/api/text").RespondsWithContent("Hello"); // 200 OK, application/json
mock.ForGet().WithPath("/api/text").RespondsWithContent(HttpStatusCode.OK, "<xml/>", "text/xml");
mock.ForGet().WithPath("/api/empty").RespondsWithEmptyContent(); // 204 No Content
mock.ForGet().WithPath("/api/binary").RespondsWith(new ByteArrayContent(bytes));
mock.ForGet().WithPath("/api/custom").RespondsWith(_ => new HttpResponseMessage(HttpStatusCode.OK));
// Build JSON content from the matched request: req.BodyAs<T>(), req.PathSegment(n), req.QueryValue(name), req.RouteValue(name)
mock.ForPost().WithPath("/api/users").RespondsWithJsonContent(req => new { Id = Guid.NewGuid(), Name = req.BodyAs<User>().Name });
// OData v4: wraps in { "value": [...] }
mock.ForGet().WithPath("/odata/items").RespondsWithODataResult(new { Id = 1 });
mock.ForGet().WithPath("/odata/items").RespondsWithODataResult(HttpStatusCode.OK, items, "https://localhost/$metadata#Items");
```
> `HttpContent` instances are reused across calls — use the lambda overload for mocks called multiple times.
## Request Capture
```csharp
// Global log
mock.Requests.HasUnexpectedRequests // bool
mock.Requests.First().WasExpected // bool; .Uri, .Method, .Body, .Timestamp, .Response also available
// Scoped collection
var captured = new RequestCollection();
mock.ForPatch().WithPath("/api/items/1").CollectingRequestsIn(captured).RespondsWithStatus(HttpStatusCode.NoContent);
captured.Count.Should().Be(1);
// Dump every request handled so far (sequence, method/URI, status/response, body) for debugging
output.WriteLine(mock.GetTrafficReport());
```
## Invocation Limits
```csharp
mock.ForGet().WithPath("/api/once").RespondsWithStatus(HttpStatusCode.OK).Once();
mock.ForGet().WithPath("/api/twice").RespondsWithStatus(HttpStatusCode.OK).Twice();
mock.ForGet().WithPath("/api/data").RespondsWithStatus(HttpStatusCode.OK).Times(3);
mock.AllMocksInvoked.Should().BeTrue(); // true when all mocks hit required count
mock.GetUninvokedMocks(); // IEnumerable<RequestMock>
```
## Response Latency
```csharp
// Delay the response to test timeout / cancellation / resilience behavior.
mock.ForGet().WithPath("/slow").RespondsWithStatus(HttpStatusCode.OK).After(TimeSpan.FromSeconds(2));
// A shorter HttpClient.Timeout or a cancelled token throws TaskCanceledException/OperationCanceledException.
```
## Reset / Clear
```csharp
mock.Reset(); // clears scheme/host inheritance from previous builder; start fresh
mock.Clear(); // removes all configured mocks
```
## FluentAssertions.Mockly (`FluentAssertions.Mockly.v8` / `.v7`)
```csharp
mock.Should().HaveAllRequestsCalled();
mock.Requests.Should().NotContainUnexpectedCalls();
mock.Requests.Should().NotBeEmpty();
mock.Requests.First().Should().BeExpected();
mock.Requests.First().Should().BeUnexpected();
```
Pliki w paczce (23)
- .editorconfig 17 KB
- .gitattributes 3 KB
- .gitignore 3 KB
- AGENTS.md 3 KB
- AcceptApiChanges.ps1 1 KB
- AcceptApiChanges.sh 1 KB
- CLAUDE.md 1 KB
- CNAME 1 KB
- CODE_OF_CONDUCT.md 5 KB
- CONTRIBUTING.md 4 KB
- Directory.Build.props 2 KB
- GitVersion.yml 1 KB
- LICENSE 1 KB
- Logo.png 149 KB
- Mockly.sln 2 KB
- Mockly.sln.DotSettings 24 KB
- PackageIcon.png 101 KB
- README.md 16 KB
- SKILL.md 7 KB
- build.cmd 1 KB
- build.ps1 3 KB
- build.sh 3 KB
- global.json 1 KB
Wersje
W bazie nie ma innych skilli o nazwie mockly.
Migawka bazy z 28.10.2026 · wersja paczki e78afb2f8b97 (skrót SHA-256 całej paczki)
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100angular-http-client
Integruje HttpClient, interceptory i interakcje z API w Angularze. - 80Angular HttpClient Migration v6
Migruje z HttpModule i Http na HttpClientModule i HttpClient w epoce Angulara 5 do 6, gdy stare API blokuje rozwój. - 91effect-http-client
Wysyła żądania HTTP w Effect: buduje żądania, dekoduje odpowiedzi, dodaje ponowienia, limity i strumieniowe pliki. - 100msw
Przechwytuje żądania sieciowe i mockuje API REST, GraphQL, SSE i WebSocket z Mock Service Worker w testach, Storybook i lokalnym developmencie, bez zmian w kodzie aplikacji. - 100csharp-testing
Opisuje wzorce testowania C# i .NET: xUnit, FluentAssertions, mocki, testy integracyjne i organizacja testów. - 100unirest-java-3
Pisze żądania HTTP w Javie 8+ przez Unirest 3.x: JSON, pliki, asynchroniczność, mocki, proxy i migrację.