MockMe by connorivy
Nuget / site data
Details
Info
Name: MockMe
The concrete type mocking library for .NET
Author: connorivy
NuGet: https://www.nuget.org/packages/MockMe/
You can find more details at https://github.com/connorivy/MockMe/
Source : https://github.com/connorivy/MockMe/
Original Readme
What is it?
MockMe is a library for mocking dependencies in your unit test projects. Unlike other libraries that can only mock interfaces and virtual methods, MockMe can mock sealed classes and non-virtual methods.
Getting Started
Imagine you have the following repository class
sealed class MyRepo
{
public int ExpensiveDatabaseCall() => // some code;
}
Download the MockMe NuGet package, then the source generators and the "MockMe.Mock" type will be available in your project. Then you can customize the behavior of the repository class as below.
using MockMe;
// use this syntax to trigger the source generator to make a mock of the provided type
// the 'mock' object will have 3 properties: Setup, Assert, and MockedObject
// hint: rebuild test project after writing this line or IntelliSense may not work correctly
var mock = Mock.Me(default(MyRepo));
// the mock.Setup object has an identical interface to the original object
// from there you can configure method behavior with 'Returns', 'Callback', 'Throws', etc
mock.Setup.ExpensiveDatabaseCall().Returns(99);
// the mock.MockedObject is a special instance of the mocked type which has the modified behavior
// other instances of the mocked type will have the original behavior
MyRepo myRepo = mock.MockedObject;
int result = myRepo.ExpensiveDatabaseCall();
Assert.Equal(99, result);
// the mock.Assert object also has an identical interface to the original object.
// you can use it to assert certain mock behaviors
mock.Assert.ExpensiveDatabaseCall().WasCalled();
Check out the Wiki for more examples.
Give it a Star
If you like this project, please give it a star!
About
Creating mocks for testing classes
How to use
Example ( source csproj, source files )
- CSharp Project
- TestClock.cs
This is the CSharp Project that references MockMe
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MockMe" Version="1.1.2" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MockData\MockData.csproj" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of MockMe in TestClock.cs
using MockMe;
namespace TestClock;
[TestClass]
public class TestClock
{
[TestMethod]
public void TestMyClock()
{
var mock = Mock.Me(default(MyClock));
mock.Setup.GetUtcNow().Returns(DateTime.Now.AddYears(-1));
mock.Setup.GetNow().Returns(DateTime.Now.AddYears(-1));
MyClock clock = mock;
Assert.AreEqual(DateTime.Now.AddYears(-1).Year, clock.GetNow().Year);
}
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- AssemblyAttributes.g.cs
- Mock.DummyDeclaration.g.cs
- Mock.g.cs
- MyClockMock.g.cs
// <auto-generated />
#pragma warning disable
using System;
namespace MockMe
{
internal static partial class Mock
{
public static object Me(global::MockMe.DummyClass unusedInstance)
{
throw new global::System.NotImplementedException();
}
}
}
#pragma warning restore
// <auto-generated />
#pragma warning disable
#nullable enable
namespace MockMe
{
internal static partial class Mock
{
[global::System.CodeDom.Compiler.GeneratedCode("MockMe", "1.1.2.0")]
public static global::MockMe.Generated.MockData.MyClockMock Me(global::MockData.MyClock? unusedInstance)
{
return new();
}
}
}
#pragma warning restore
// <auto-generated />
#pragma warning disable
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using MockMe;
using MockMe.Mocks;
using MockMe.Mocks.ClassMemberMocks;
using MockMe.Mocks.ClassMemberMocks.CallTracker;
namespace MockMe.Generated.MockData
{
[global::System.CodeDom.Compiler.GeneratedCode("MockMe", "1.1.2.0")]
internal class MyClockMock
: global::MockMe.Abstractions.SealedTypeMock<global::MockData.MyClock>
{
public MyClockMock()
{
this.Setup = new MyClockMockSetup();
this.CallTracker = new MyClockMockSetup.MyClockMockCallTracker(this.Setup);
this.Assert = new MyClockMockSetup.MyClockMockCallTracker.MyClockMockAsserter(this.CallTracker);
global::MockMe.MockStore<global::MockData.MyClock>.Store.TryAdd(this.MockedObject, this);
}
public MyClockMockSetup Setup { get; }
public MyClockMockSetup.MyClockMockCallTracker.MyClockMockAsserter Assert { get; }
private MyClockMockSetup.MyClockMockCallTracker CallTracker { get; }
internal sealed class Patchc7ee80333a4e4f9c8cd65e1c335b3b10
{
private static bool Prefix(global::MockData.MyClock __instance, ref global::System.DateTime __result)
{
if (global::MockMe.MockStore<global::MockData.MyClock>.TryGetValue<MyClockMock>(__instance, out var mock))
{
__result = mock.CallTracker.GetNow();
return false;
}
return true;
}
}
internal sealed class Patchba0bfb2023b14b7a948f049392536934
{
private static bool Prefix(global::MockData.MyClock __instance, ref global::System.DateTime __result)
{
if (global::MockMe.MockStore<global::MockData.MyClock>.TryGetValue<MyClockMock>(__instance, out var mock))
{
__result = mock.CallTracker.GetUtcNow();
return false;
}
return true;
}
}
static MyClockMock()
{
var harmony = new global::HarmonyLib.Harmony("com.mockme.patch");
var originalPatchc7ee80333a4e4f9c8cd65e1c335b3b10 = typeof(global::MockData.MyClock).GetMethod("GetNow", new Type[] { } );
var Patchc7ee80333a4e4f9c8cd65e1c335b3b10 = typeof(Patchc7ee80333a4e4f9c8cd65e1c335b3b10).GetMethod("Prefix", global::System.Reflection.BindingFlags.Static | global::System.Reflection.BindingFlags.NonPublic);
harmony.Patch(originalPatchc7ee80333a4e4f9c8cd65e1c335b3b10, prefix: new HarmonyMethod(Patchc7ee80333a4e4f9c8cd65e1c335b3b10));
var originalPatchba0bfb2023b14b7a948f049392536934 = typeof(global::MockData.MyClock).GetMethod("GetUtcNow", new Type[] { } );
var Patchba0bfb2023b14b7a948f049392536934 = typeof(Patchba0bfb2023b14b7a948f049392536934).GetMethod("Prefix", global::System.Reflection.BindingFlags.Static | global::System.Reflection.BindingFlags.NonPublic);
harmony.Patch(originalPatchba0bfb2023b14b7a948f049392536934, prefix: new HarmonyMethod(Patchba0bfb2023b14b7a948f049392536934));
}
}
[global::System.CodeDom.Compiler.GeneratedCode("MockMe", "1.1.2.0")]
internal class MyClockMockSetup : global::MockMe.Mocks.ClassMemberMocks.Setup.MemberMockSetup
{
private global::MockMe.Mocks.ClassMemberMocks.MemberMock<global::System.DateTime>? GetNow_BagStore;
public global::MockMe.Mocks.ClassMemberMocks.MemberMock<global::System.DateTime> GetNow()
{
return this.GetNow_BagStore ??= new();;
}
private global::MockMe.Mocks.ClassMemberMocks.MemberMock<global::System.DateTime>? GetUtcNow_BagStore;
public global::MockMe.Mocks.ClassMemberMocks.MemberMock<global::System.DateTime> GetUtcNow()
{
return this.GetUtcNow_BagStore ??= new();;
}
[global::System.CodeDom.Compiler.GeneratedCode("MockMe", "1.1.2.0")]
internal class MyClockMockCallTracker : MockCallTracker
{
private readonly MyClockMockSetup setup;
public MyClockMockCallTracker(MyClockMockSetup setup)
{
this.setup = setup;
}
private int GetNow_CallStore;
public global::System.DateTime GetNow()
{
this.GetNow_CallStore++;
return MockCallTracker.CallMemberMock<global::System.DateTime>(this.setup.GetNow_BagStore);
}
private int GetUtcNow_CallStore;
public global::System.DateTime GetUtcNow()
{
this.GetUtcNow_CallStore++;
return MockCallTracker.CallMemberMock<global::System.DateTime>(this.setup.GetUtcNow_BagStore);
}
[global::System.CodeDom.Compiler.GeneratedCode("MockMe", "1.1.2.0")]
internal class MyClockMockAsserter : MockAsserter
{
private readonly MyClockMockSetup.MyClockMockCallTracker tracker;
public MyClockMockAsserter(MyClockMockSetup.MyClockMockCallTracker tracker)
{
this.tracker = tracker;
}
public global::MockMe.Asserters.MemberAsserter GetNow() =>
new(this.tracker.GetNow_CallStore);
public global::MockMe.Asserters.MemberAsserter GetUtcNow() =>
new(this.tracker.GetUtcNow_CallStore);
}
}
}
}
#pragma warning restore
Usefull
Download Example (.NET C# )
Share MockMe
https://ignatandrei.github.io/RSCG_Examples/v2/docs/MockMe