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
9 changes: 9 additions & 0 deletions website/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ export default defineConfig({
link: 'https://www.nuget.org/packages/DependencyModules.Conventions/',
},
{ text: 'xUnit', link: 'https://www.nuget.org/packages/DependencyModules.xUnit/' },
{
text: 'NSubstitute',
link: 'https://www.nuget.org/packages/DependencyModules.NSubstitute/',
},
{ text: 'Moq', link: 'https://www.nuget.org/packages/DependencyModules.Moq/' },
{
text: 'FakeItEasy',
link: 'https://www.nuget.org/packages/DependencyModules.FakeItEasy/',
},
],
},
],
Expand Down
47 changes: 37 additions & 10 deletions website/guide/testing-mocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,61 @@ holding. You wire nothing together yourself.
Note what stayed real: `SummaryProvider` was not mocked, so the call still travels
`Weather` → `SummaryProvider` → `IAiSummaryProvider`. Only the leaf was swapped.

::: tip Register the mocking library once
`[Mock]` needs a mocking framework, supplied by a separate package. Pick the one you already use:
## Choosing a mocking library

`[Mock]` does not depend on a particular mocking library. It defines a seam, and a small package
fills it — so use whichever library you already have:

| Package | Attribute |
|---|---|
| `DependencyModules.NSubstitute` | `[NSubstituteSupport]` |
| `DependencyModules.Moq` | `[MoqSupport]` |
| `DependencyModules.FakeItEasy` | `[FakeItEasySupport]` |

Install one and apply its attribute. Like the module attributes it works at assembly, class or
method level, and assembly is usually right:

```shell
dotnet add package DependencyModules.NSubstitute
dotnet add package DependencyModules.Moq
```

```csharp
[assembly: NSubstituteSupport]
[assembly: MoqSupport]
```

Without one, `[Mock]` fails with a message telling you so. Like the module attributes it works at
assembly, class or method level; assembly is almost always right.
Without one, `[Mock]` fails with a message telling you so.

With NSubstitute and FakeItEasy the injected instance is also what you configure. Moq separates the
two, so the container gets `Mock<T>.Object` and you reach the mock with `Mock.Get(instance)`:
### The same test in each

```csharp
Mock.Get(summaryProvider).Setup(x => x.Summarize(It.IsAny<string>())).Returns("mild");
Only the configuration lines differ — `[Mock]`, the injection and the assertions are identical. The
example above is NSubstitute; here are the other two:

::: code-group

```csharp [NSubstitute]
temperatureProvider.GetTemperature().Returns(38);
aiSummaryProvider.GetSummary().Returns("Sunny");
```

```csharp [Moq]
Mock.Get(temperatureProvider).Setup(x => x.GetTemperature()).Returns(38);
Mock.Get(aiSummaryProvider).Setup(x => x.GetSummary()).Returns("Sunny");
```

```csharp [FakeItEasy]
A.CallTo(() => temperatureProvider.GetTemperature()).Returns(38);
A.CallTo(() => aiSummaryProvider.GetSummary()).Returns("Sunny");
```

:::

The `Mock.Get` in the Moq version is the one difference worth knowing about. NSubstitute and
FakeItEasy hand you an object that *is* the mock, so the parameter the container injected is the
thing you configure. Moq keeps the two apart — the container receives `Mock<T>.Object`, and
`Mock.Get(instance)` gets you back to the `Mock<T>` to set expectations on.

Unconfigured members return `default` rather than throwing, in all three.

## When you want a real object, not a mock

A mock is right when you intend to **assert on the interaction** — what was called, with which
Expand Down
7 changes: 5 additions & 2 deletions website/guide/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ real modules:

```shell
dotnet add package DependencyModules.xUnit
dotnet add package DependencyModules.NSubstitute
```

```csharp
Expand Down Expand Up @@ -89,9 +88,13 @@ every test needs in one file at the assembly level:
using DependencyModules.NSubstitute;

[assembly: ApplicationModule]
[assembly: NSubstituteSupport]
[assembly: NSubstituteSupport] // or [MoqSupport] / [FakeItEasySupport]
```

`NSubstituteSupport` is what enables [`[Mock]`](/guide/testing-mocks), and it comes from a separate
package — one per mocking library, so use whichever you already have. See
[choosing a mocking library](/guide/testing-mocks#choosing-a-mocking-library).

Every test in the project now gets `ApplicationModule` without saying so:

```csharp
Expand Down
Loading