From 86e9a52148c37de2b2d88f1f03d4ebf87ba6279c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 30 Jan 2026 19:19:08 +0100 Subject: [PATCH 1/4] docs: add documentation for delegates --- .../{06-analyzers.md => 07-analyzers.md} | 0 .../{07-comparison.md => 08-comparison.md} | 0 Docs/pages/advanced-features/_category_.json | 7 ++ .../01-httpclient.md} | 2 +- Docs/pages/special-types/02-delegates.md | 92 ++++++++++++++++++ Docs/pages/special-types/_category_.json | 7 ++ Mockolate.slnx | 13 ++- README.md | 96 ++++++++++++++++++- 8 files changed, 212 insertions(+), 5 deletions(-) rename Docs/pages/{06-analyzers.md => 07-analyzers.md} (100%) rename Docs/pages/{07-comparison.md => 08-comparison.md} (100%) create mode 100644 Docs/pages/advanced-features/_category_.json rename Docs/pages/{05-httpclient.md => special-types/01-httpclient.md} (98%) create mode 100644 Docs/pages/special-types/02-delegates.md create mode 100644 Docs/pages/special-types/_category_.json diff --git a/Docs/pages/06-analyzers.md b/Docs/pages/07-analyzers.md similarity index 100% rename from Docs/pages/06-analyzers.md rename to Docs/pages/07-analyzers.md diff --git a/Docs/pages/07-comparison.md b/Docs/pages/08-comparison.md similarity index 100% rename from Docs/pages/07-comparison.md rename to Docs/pages/08-comparison.md diff --git a/Docs/pages/advanced-features/_category_.json b/Docs/pages/advanced-features/_category_.json new file mode 100644 index 00000000..3d6ad32a --- /dev/null +++ b/Docs/pages/advanced-features/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Advanced Features", + "position": 5, + "link": { + "type": "generated-index" + } +} diff --git a/Docs/pages/05-httpclient.md b/Docs/pages/special-types/01-httpclient.md similarity index 98% rename from Docs/pages/05-httpclient.md rename to Docs/pages/special-types/01-httpclient.md index 6a98e93c..672cc61c 100644 --- a/Docs/pages/05-httpclient.md +++ b/Docs/pages/special-types/01-httpclient.md @@ -1,4 +1,4 @@ -# Mocking HttpClient +# HttpClient Mockolate supports mocking `HttpClient` out of the box, with no special configuration required. You can set up, use, and verify HTTP interactions just like with any other interface or class. diff --git a/Docs/pages/special-types/02-delegates.md b/Docs/pages/special-types/02-delegates.md new file mode 100644 index 00000000..68cae2fb --- /dev/null +++ b/Docs/pages/special-types/02-delegates.md @@ -0,0 +1,92 @@ +# Delegates + +Mockolate supports mocking delegates including `Action`, `Func`, and custom delegates. + +### Setup + +Use `SetupMock.Delegate(...)` to configure delegate behavior. + +```csharp +// Mock Action delegate +Action myAction = Mock.Create(); +myAction.SetupMock.Delegate().Do(() => Console.WriteLine("Action invoked!")); + +// Mock Func delegate +Func myFunc = Mock.Create>(); +myFunc.SetupMock.Delegate().Returns(42); +``` + +For custom delegates with parameters: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate int Calculate(int x, string operation); + +// Create and setup the mock +Calculate calculator = Mock.Create(); +calculator.SetupMock.Delegate(It.IsAny(), It.Is("add")) + .Returns((x, operation) => x + 10); +``` + +Delegates with `ref` and `out` parameters are also supported: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate void ProcessData(int input, ref int value, out int result); + +// Create and setup the mock +ProcessData processor = Mock.Create(); +processor.SetupMock.Delegate(It.IsAny(), It.IsRef(v => v + 1), It.IsOut(() => 100)); +``` + +- Use `.Do(...)` to run code when the delegate is invoked. +- Use `.Returns(...)` to specify the return value for `Func` delegates. +- Use `.Throws(...)` to specify an exception to throw. +- Use `.Returns(...)` and `.Throws(...)` repeatedly to define a sequence of behaviors. +- Full [parameter matching](https://awexpect.com/docs/mockolate/setup#parameter-matching) support for delegate + parameters including `ref` and `out` parameters. + +### Verification + +You can verify that delegates were invoked with specific arguments: + +```csharp +// Verify Action was invoked at least once +Action myAction = Mock.Create(); +myAction.Invoke(); +myAction.VerifyMock.Invoked().AtLeastOnce(); + +// Verify Func was invoked exactly once +Func myFunc = Mock.Create>(); +_ = myFunc(); +myFunc.VerifyMock.Invoked().Once(); +``` + +For custom delegates with parameters: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate int Calculate(int x, string operation); + +// Create, invoke, and verify the mock +Calculate calculator = Mock.Create(); +_ = calculator(5, "add"); +calculator.VerifyMock.Invoked(It.IsAny(), It.Is("add")).Once(); +``` + +Delegates with `ref` and `out` parameters are also supported: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate void ProcessData(int input, ref int value, out int result); + +// Create, invoke, and verify the mock +ProcessData processor = Mock.Create(); +int val = 0; +processor(1, ref val, out int res); +processor.VerifyMock.Invoked(It.IsAny(), It.IsRef(), It.IsOut()).Once(); +``` + +**Note:** +Delegate parameters also +support [argument matchers](https://awexpect.com/docs/mockolate/verify-interactions#argument-matchers). diff --git a/Docs/pages/special-types/_category_.json b/Docs/pages/special-types/_category_.json new file mode 100644 index 00000000..3ae10eba --- /dev/null +++ b/Docs/pages/special-types/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Special Types", + "position": 6, + "link": { + "type": "generated-index" + } +} diff --git a/Mockolate.slnx b/Mockolate.slnx index eecadc8b..aa75d4d5 100644 --- a/Mockolate.slnx +++ b/Mockolate.slnx @@ -46,9 +46,16 @@ - - - + + + + + + + + + + diff --git a/README.md b/README.md index e8d60b1d..ced26416 100644 --- a/README.md +++ b/README.md @@ -521,7 +521,9 @@ If the order is incorrect or a call is missing, a `MockVerificationException` wi This is useful for ensuring that your test setup and test execution match. If any setup was not used, this method returns `false`. -## Mocking HttpClient +## Special Types + +### HttpClient Mockolate supports mocking `HttpClient` out of the box, with no special configuration required. You can set up, use, and verify HTTP interactions just like with any other interface or class. @@ -553,6 +555,98 @@ httpClient.VerifyMock.Invoked.PostAsync( As they therefore all forward to the `SendAsync` method, you can mix using a string or an `Uri` parameter in setup or verification. +### Delegates + +Mockolate supports mocking delegates including `Action`, `Func`, and custom delegates. + +#### Setup + +Use `SetupMock.Delegate(...)` to configure delegate behavior. + +```csharp +// Mock Action delegate +Action myAction = Mock.Create(); +myAction.SetupMock.Delegate().Do(() => Console.WriteLine("Action invoked!")); + +// Mock Func delegate +Func myFunc = Mock.Create>(); +myFunc.SetupMock.Delegate().Returns(42); +``` + +For custom delegates with parameters: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate int Calculate(int x, string operation); + +// Create and setup the mock +Calculate calculator = Mock.Create(); +calculator.SetupMock.Delegate(It.IsAny(), It.Is("add")) + .Returns((x, operation) => x + 10); +``` + +Delegates with `ref` and `out` parameters are also supported: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate void ProcessData(int input, ref int value, out int result); + +// Create and setup the mock +ProcessData processor = Mock.Create(); +processor.SetupMock.Delegate(It.IsAny(), It.IsRef(v => v + 1), It.IsOut(() => 100)); +``` + +- Use `.Do(...)` to run code when the delegate is invoked. +- Use `.Returns(...)` to specify the return value for `Func` delegates. +- Use `.Throws(...)` to specify an exception to throw. +- Use `.Returns(...)` and `.Throws(...)` repeatedly to define a sequence of behaviors. +- Full [parameter matching](#parameter-matching) support for delegate + parameters including `ref` and `out` parameters. + +#### Verification + +You can verify that delegates were invoked with specific arguments: + +```csharp +// Verify Action was invoked at least once +Action myAction = Mock.Create(); +myAction.Invoke(); +myAction.VerifyMock.Invoked().AtLeastOnce(); + +// Verify Func was invoked exactly once +Func myFunc = Mock.Create>(); +_ = myFunc(); +myFunc.VerifyMock.Invoked().Once(); +``` + +For custom delegates with parameters: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate int Calculate(int x, string operation); + +// Create, invoke, and verify the mock +Calculate calculator = Mock.Create(); +_ = calculator(5, "add"); +calculator.VerifyMock.Invoked(It.IsAny(), It.Is("add")).Once(); +``` + +Delegates with `ref` and `out` parameters are also supported: + +```csharp +// Define a custom delegate (typically declared at type level) +public delegate void ProcessData(int input, ref int value, out int result); + +// Create, invoke, and verify the mock +ProcessData processor = Mock.Create(); +int val = 0; +processor(1, ref val, out int res); +processor.VerifyMock.Invoked(It.IsAny(), It.IsRef(), It.IsOut()).Once(); +``` + +**Note:** +Delegate parameters also support [argument matchers](#argument-matcher). + ## Analyzers Mockolate ships with some Roslyn analyzers to help you adopt best practices and catch issues early, at compile time. From 326ac63b4b1195fbcdc0c80862985425226cab23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 30 Jan 2026 19:21:01 +0100 Subject: [PATCH 2/4] Make subheaders bold --- Docs/pages/special-types/02-delegates.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Docs/pages/special-types/02-delegates.md b/Docs/pages/special-types/02-delegates.md index 68cae2fb..15a21087 100644 --- a/Docs/pages/special-types/02-delegates.md +++ b/Docs/pages/special-types/02-delegates.md @@ -2,7 +2,7 @@ Mockolate supports mocking delegates including `Action`, `Func`, and custom delegates. -### Setup +**Setup** Use `SetupMock.Delegate(...)` to configure delegate behavior. @@ -46,7 +46,7 @@ processor.SetupMock.Delegate(It.IsAny(), It.IsRef(v => v + 1), It.IsOu - Full [parameter matching](https://awexpect.com/docs/mockolate/setup#parameter-matching) support for delegate parameters including `ref` and `out` parameters. -### Verification +**Verification** You can verify that delegates were invoked with specific arguments: diff --git a/README.md b/README.md index ced26416..61b3bc33 100644 --- a/README.md +++ b/README.md @@ -559,7 +559,7 @@ httpClient.VerifyMock.Invoked.PostAsync( Mockolate supports mocking delegates including `Action`, `Func`, and custom delegates. -#### Setup +**Setup** Use `SetupMock.Delegate(...)` to configure delegate behavior. @@ -603,7 +603,7 @@ processor.SetupMock.Delegate(It.IsAny(), It.IsRef(v => v + 1), It.IsOu - Full [parameter matching](#parameter-matching) support for delegate parameters including `ref` and `out` parameters. -#### Verification +**Verification** You can verify that delegates were invoked with specific arguments: From ba409eda7b5620772de88b5e8844f82336193d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 30 Jan 2026 19:25:28 +0100 Subject: [PATCH 3/4] Fix typo --- Docs/pages/01-create-mocks.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/pages/01-create-mocks.md b/Docs/pages/01-create-mocks.md index ef083d7e..687653dc 100644 --- a/Docs/pages/01-create-mocks.md +++ b/Docs/pages/01-create-mocks.md @@ -73,7 +73,7 @@ var sut2 = factory.Create(); Using a factory allows you to create multiple mocks with identical, centrally configured behavior. This is especially useful when you need consistent mock setups across multiple tests or for different types. -## Wrapping Existing Instances +## Wrapping existing instances You can wrap an existing instance with mock tracking using `Mock.Wrap()`. This allows you to track interactions with a real object: diff --git a/README.md b/README.md index 61b3bc33..94b98c34 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ var sut2 = factory.Create(); Using a factory allows you to create multiple mocks with identical, centrally configured behavior. This is especially useful when you need consistent mock setups across multiple tests or for different types. -## Wrapping Existing Instances +## Wrapping existing instances You can wrap an existing instance with mock tracking using `Mock.Wrap()`. This allows you to track interactions with a real object: From f869386ab56aa9366ccc49ea5adf3d0556f745cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 30 Jan 2026 19:28:01 +0100 Subject: [PATCH 4/4] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94b98c34..71a3292f 100644 --- a/README.md +++ b/README.md @@ -645,7 +645,7 @@ processor.VerifyMock.Invoked(It.IsAny(), It.IsRef(), It.IsOut()). ``` **Note:** -Delegate parameters also support [argument matchers](#argument-matcher). +Delegate parameters also support [argument matchers](#argument-matchers). ## Analyzers