Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions Docs/pages/01-create-mocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,37 @@ var classMock = Mock.Create<MyChocolateDispenser>(
### `MockBehavior` options

- `ThrowWhenNotSetup` (bool):
- If `false` (default), the mock will return a default value (see `DefaultValue`).
- If `true`, the mock will throw an exception when a method or property is called without a setup.
- If `false` (default), the mock will return a default value (see `DefaultValue`).
- If `true`, the mock will throw an exception when a method or property is called without a setup.
- `SkipBaseClass` (bool):
- If `false` (default), the mock will call the base class implementation and use its return values as default
values, if no explicit setup is defined.
- If `true`, the mock will not call any base class implementations.
- If `false` (default), the mock will call the base class implementation and use its return values as default
values, if no explicit setup is defined.
- If `true`, the mock will not call any base class implementations.
- `Initialize<T>(params Action<IMockSetup<T>>[] setups)`:
- Automatically initialize all mocks of type T with the given setups when they are created.
- The callback can optionally receive an additional counter parameter which allows to differentiate between multiple
instances. This is useful when you want to ensure that you can distinguish between different automatically created
instances.
- Automatically initialize all mocks of type T with the given setups when they are created.
- The callback can optionally receive an additional counter parameter which allows to differentiate between multiple
instances. This is useful when you want to ensure that you can distinguish between different automatically created
instances.
- `DefaultValue` (IDefaultValueGenerator):
- Customizes how default values are generated for methods/properties that are not set up.
- The default implementation provides sensible defaults for the most common use cases:
- Empty collections for collection types (e.g., `IEnumerable<T>`, `List<T>`, etc.)
- Empty string for `string`
- Completed tasks for `Task`, `Task<T>`, `ValueTask` and `ValueTask<T>`
- Tuples with recursively defaulted values
- `null` for other reference types
- You can provide custom default values for specific types using `.WithDefaultValueFor<T>()`:
```csharp
var behavior = MockBehavior.Default
.WithDefaultValueFor<string>(() => "default")
.WithDefaultValueFor<int>(() => 42);
var sut = Mock.Create<IChocolateDispenser>(behavior);
```
This is useful when you want mocks to return specific default values for certain types instead of the standard
defaults (e.g., `null`, `0`, empty strings).
- Customizes how default values are generated for methods/properties that are not set up.
- The default implementation provides sensible defaults for the most common use cases:
- Empty collections for collection types (e.g., `IEnumerable<T>`, `List<T>`, etc.)
- Empty string for `string`
- Completed tasks for `Task`, `Task<T>`, `ValueTask` and `ValueTask<T>`
- Tuples with recursively defaulted values
- `null` for other reference types
- You can provide custom default values for specific types using `.WithDefaultValueFor<T>()`:
```csharp
var behavior = MockBehavior.Default
.WithDefaultValueFor<string>(() => "default")
.WithDefaultValueFor<int>(() => 42);
var sut = Mock.Create<IChocolateDispenser>(behavior);
```
This is useful when you want mocks to return specific default values for certain types instead of the standard
defaults (e.g., `null`, `0`, empty strings).
- `.UseConstructorParametersFor<T>(object?[])`:
- Configures constructor parameters to use when creating mocks of type `T`, unless explicit parameters are provided
during mock creation via `BaseClass.WithConstructorParameters(…)`.
- Configures constructor parameters to use when creating mocks of type `T`, unless explicit parameters are provided
during mock creation via `BaseClass.WithConstructorParameters(…)`.

## Using a factory for shared behavior

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ sut.SetupMock.Method.Dispense(It.IsAny<string>(), It.IsAny<int>())
.Do((count, _, _) => Console.WriteLine($"Call #{count}"));

sut.SetupMock.Property.TotalDispensed.OnGet
.Do((count, value) => Console.WriteLine($"Read #{count}, value: {value}"));
.Do((count, value) => Console.WriteLine($"Read #{count}, value: {value}"));
```
162 changes: 153 additions & 9 deletions Docs/pages/special-types/01-httpclient.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ verify HTTP interactions just like with any other interface or class.

```csharp
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method.PostAsync(
It.IsAny<string>(),
It.IsStringContent())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
httpClient.SetupMock.Method
.PostAsync(
It.IsAny<string>(),
It.IsStringContent())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

HttpResponseMessage result = await httpClient.PostAsync("https://aweXpect.com/api/chocolate/dispense",
new StringContent("""
{ "type": "Dark", "amount": 3 }
""", Encoding.UTF8, "application/json"));
new StringContent("""
{ "type": "Dark", "amount": 3 }
""", Encoding.UTF8, "application/json"));

await That(result.IsSuccessStatusCode).IsTrue();
httpClient.VerifyMock.Invoked.PostAsync(
It.IsUri("*aweXpect.com/api/chocolate/dispense*").ForHttps(),
It.IsStringContent("application/json").WithBodyMatching("*\"type\": \"Dark\"*\"amount\": 3*")).Once();
It.IsUri("*aweXpect.com/api/chocolate/dispense*").ForHttps(),
It.IsStringContent("application/json").WithBodyMatching("*\"type\": \"Dark\"*\"amount\": 3*")).Once();
```

**Notes:**
Expand All @@ -29,3 +30,146 @@ httpClient.VerifyMock.Invoked.PostAsync(
- Under the hood, the setups, requests and verifications are forwarded to a mocked `HttpMessageHandler`.
As they therefore all forward to the `SendAsync` method, you can mix using a string or an `Uri` parameter in setup or
verification.

## All HTTP Methods

Mockolate supports all standard HTTP methods:

```csharp
// GET
httpClient.SetupMock.Method
.GetAsync(It.IsAny<string>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NoContent));

// POST
httpClient.SetupMock.Method
.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

// PUT
httpClient.SetupMock.Method
.PutAsync(It.IsAny<string>(), It.IsAny<HttpContent>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

// DELETE
httpClient.SetupMock.Method
.DeleteAsync(It.IsAny<string>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NoContent));

// PATCH
httpClient.SetupMock.Method
.PatchAsync(It.IsAny<string>(), It.IsAny<HttpContent>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
```

For all HTTP methods you can add an optional cancellation token parameter.
If no parameter is provided, it matches any `CancellationToken`:

```csharp
var cts = new CancellationTokenSource();
httpClient.SetupMock.Method
.GetAsync(It.IsAny<string>(), It.Is(cts.Token))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

await httpClient.GetAsync("https://example.com", cts.Token);
```

## URI matching

Use `It.IsUri(string?)` to match URIs using a wildcard pattern against the string representation of the URI.
The pattern supports `*` to match zero or more characters and `?` to match a single character.

### Scheme

Filter requests by URI scheme using `.ForHttps()` or `.ForHttp()`:

```csharp
// Match only HTTPS requests
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri("*aweXpect.com*").ForHttps())
.Once();

// Match only HTTP requests
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri("*aweXpect.com*").ForHttp())
.Never();
```

### Host

Filter requests by host using `.WithHost(string?)`. You can provide a wildcard pattern to match against the host name:

```csharp
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri().WithHost("*aweXpect.com*"))
.Once();
```

### Port

Filter requests on a specific port using `.WithPort(int)`:

```csharp
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri().WithPort(443))
.Once();
```

### Path

Filter requests by path using `.WithPath(string?)`. You can provide a wildcard pattern to match against the path:

```csharp
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri().WithPath("/foo/*"))
.Once();
```

### Query

Filter requests by query using `.WithQuery(string?)`. You can provide a wildcard pattern to match against the query:

```csharp
httpClient.VerifyMock.Invoked
.GetAsync(It.IsUri().WithQuery("*x=42*"))
.Once();
```

## Content Matching

### String content

Use `It.IsStringContent(string?)` to match string content types, optionally providing an expected media type header
value:

```csharp
httpClient.SetupMock.Method
.PostAsync(
It.IsAny<string>(),
It.IsStringContent("application/json").WithBodyMatching("*\"type\": \"Dark\"*"))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
```

To verify against the string content, use the following methods:

- `.WithBody(string)`: to match content exactly as provided
- `.WithBodyMatching(string)`: to match content using wildcard patterns
- `.WithBodyMatching(string).AsRegex()`: to match content using regular expressions

### Binary content

Use `It.IsBinaryContent(string?)` to match binary content types, optionally providing an expected media type header
value:

```csharp
httpClient.SetupMock.Method
.PostAsync(
It.IsAny<string>(),
It.IsBinaryContent("application/octet-stream"))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
```

To verify against the binary content, use the following methods:

- `.EqualTo(byte[])`: to match content exactly as provided
- `.Containing(byte[])`: to match content to contain the provided byte sequence in order
Loading
Loading