DoNotMock 0.0.1
See the version list below for details.
dotnet add package DoNotMock --version 0.0.1
NuGet\Install-Package DoNotMock -Version 0.0.1
<PackageReference Include="DoNotMock" Version="0.0.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="DoNotMock" Version="0.0.1" />
<PackageReference Include="DoNotMock"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add DoNotMock --version 0.0.1
#r "nuget: DoNotMock, 0.0.1"
#:package DoNotMock@0.0.1
#addin nuget:?package=DoNotMock&version=0.0.1
#tool nuget:?package=DoNotMock&version=0.0.1
DoNotMock.NET
A .NET implementation of the [DoNotMock]
attribute with built-in Roslyn analyzer, inspired by Google's "Error Prone" tool. This attribute helps enforce proper test double usage by marking types that should not be mocked in tests.
Inspiration
- https://testing.googleblog.com/2024/02/increase-test-fidelity-by-avoiding-mocks.html
- https://testing.googleblog.com/2013/05/testing-on-toilet-dont-overuse-mocks.html
- https://android.googlesource.com/platform/frameworks/support/%2B/refs/heads/androidx-core-core-role-release/docs/do_not_mock.md
- https://www.baeldung.com/mockito-annotations#donotmock-annotation
Why should you avoid Mocks?
Mocking is a powerful tool for unit testing, but it can cause some issues of its own:
- Mocks maintain none of the same behavior as the real code.
- They lock your tests into one particular implementation.
The [DoNotMock]
attribute, combined with the built-in Roslyn analyzer, helps enforce these design decisions by:
- Marking types that should not be mocked
- Providing compile-time errors when these types are mocked
- Encouraging the use of real implementations or hand-written test doubles
Installation
dotnet add package DoNotMock
The package includes both the attribute and its analyzer.
Usage
Mark any class or interface that should not be mocked with the [DoNotMock]
attribute:
using DoNotMock;
[DoNotMock("Use NullEmailSender instead")]
public interface IEmailSender
{
Task SendEmailAsync(string to, string subject, string body);
}
// The analyzer will prevent mocking this interface:
var mock = new Mock<IEmailSender>(); // Error DNMK001: Type 'IEmailSender' is marked with [DoNotMock] and should not be mocked
Rule DNMK001: Type marked with [DoNotMock] should not be mocked
This rule is triggered when code attempts to mock a type that is marked with the [DoNotMock]
attribute. The analyzer detects mock creation and setup patterns from popular mocking frameworks including:
- Moq
- NSubstitute
- FakeItEasy
Examples of violations
// Using Moq
var mock = new Mock<IEmailSender>();
mock.Setup(x => x.SendEmailAsync(...));
// Using NSubstitute
var mock = Substitute.For<IEmailSender>();
mock.SendEmailAsync(...).Returns(Task.CompletedTask);
// Using FakeItEasy
var mock = A.Fake<IEmailSender>();
A.CallTo(() => mock.SendEmailAsync(...)).Returns(Task.CompletedTask);
How to fix violations
Instead of mocking, use one of these approaches:
- Use the real implementation in your tests
- Create a test-specific implementation:
public class TestEmailSender : IEmailSender
{
public List<(string To, string Subject, string Body)> SentEmails { get; } = new();
public Task SendEmailAsync(string to, string subject, string body)
{
SentEmails.Add((to, subject, body));
return Task.CompletedTask;
}
}
// In your test:
var emailSender = new TestEmailSender();
await emailSender.SendEmailAsync("test@example.com", "Test", "Hello");
emailSender.SentEmails.Should().ContainSingle()
.Which.Should().BeEquivalentTo(
(To: "test@example.com", Subject: "Test", Body: "Hello"));
- Use a null implementation if the dependency is optional:
public class NullEmailSender : IEmailSender
{
public static IEmailSender Instance { get; } = new NullEmailSender();
public Task SendEmailAsync(string to, string subject, string body) => Task.CompletedTask;
}
Building from Source
Requirements:
- .NET SDK 8.0 or later
git clone https://github.com/ductoman16/DoNotMock.NET.git
cd DoNotMock.NET
dotnet build
dotnet test
Contributing
Contributions are welcome! Please read our Contributing Guidelines before submitting a pull request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.