Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport.Abstractions" Version="2.1.0" />
<PackageVersion Include="Microsoft.Testing.Platform" Version="2.1.0" />
<PackageVersion Include="Microsoft.Testing.Platform.MSBuild" Version="2.1.0" />
<PackageVersion Include="Imposter" Version="0.1.9"/>
<PackageVersion Include="Mockolate" Version="2.1.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="System.Threading.Channels" Version="9.0.0" />
<PackageVersion Include="ModularPipelines.DotNet" Version="3.1.90" />
Expand Down
62 changes: 60 additions & 2 deletions TUnit.Mocks.Benchmarks/CallbackBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using BenchmarkDotNet.Attributes;
using FakeItEasy;
using Imposter.Abstractions;
using Mockolate;
using Moq;
using NSubstitute;

Expand All @@ -25,12 +27,39 @@ public int TUnitMocks_Callback()
return count;
}

[Benchmark(Description = "Imposter")]
public int Imposter_Callback()
{
var count = 0;
var imposter = INotificationService.Imposter();
imposter.Send(Arg<string>.Any(), Arg<string>.Any())
.Callback((_, _) => count++);

var instance = imposter.Instance();
instance.Send("user@test.com", "Hello");
instance.Send("user@test.com", "World");
return count;
}

[Benchmark(Description = "Mockolate")]
public int Mockolate_Callback()
{
var count = 0;
var svc = INotificationService.CreateMock();
svc.Mock.Setup.Send(Mockolate.It.IsAny<string>(), Mockolate.It.IsAny<string>())
.Do(() => count++);

svc.Send("user@test.com", "Hello");
svc.Send("user@test.com", "World");
return count;
}

[Benchmark(Description = "Moq")]
public int Moq_Callback()
{
var count = 0;
var mock = new Moq.Mock<INotificationService>();
mock.Setup(x => x.Send(It.IsAny<string>(), It.IsAny<string>()))
mock.Setup(x => x.Send(Moq.It.IsAny<string>(), Moq.It.IsAny<string>()))
.Callback(() => count++);

var svc = mock.Object;
Expand Down Expand Up @@ -80,12 +109,41 @@ public string TUnitMocks_CallbackWithArgs()
return lastMessage;
}

[Benchmark(Description = "Imposter (with args)")]
public string Imposter_CallbackWithArgs()
{
var lastMessage = "";
var imposter = ILogger.Imposter();
imposter.Log(Arg<string>.Any(), Arg<string>.Any())
.Callback((_, msg) => lastMessage = msg);

var instance = imposter.Instance();
instance.Log("INFO", "Test message 1");
instance.Log("WARN", "Test message 2");
instance.Log("ERROR", "Test message 3");
return lastMessage;
}

[Benchmark(Description = "Mockolate (with args)")]
public string Mockolate_CallbackWithArgs()
{
var lastMessage = "";
var logger = ILogger.CreateMock();
logger.Mock.Setup.Log(Mockolate.It.IsAny<string>(), Mockolate.It.IsAny<string>())
.Do((_, msg) => lastMessage = msg);

logger.Log("INFO", "Test message 1");
logger.Log("WARN", "Test message 2");
logger.Log("ERROR", "Test message 3");
return lastMessage;
}

[Benchmark(Description = "Moq (with args)")]
public string Moq_CallbackWithArgs()
{
var lastMessage = "";
var mock = new Moq.Mock<ILogger>();
mock.Setup(x => x.Log(It.IsAny<string>(), It.IsAny<string>()))
mock.Setup(x => x.Log(Moq.It.IsAny<string>(), Moq.It.IsAny<string>()))
.Callback<string, string>((level, msg) => lastMessage = msg);

var logger = mock.Object;
Expand Down
61 changes: 58 additions & 3 deletions TUnit.Mocks.Benchmarks/CombinedWorkflowBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using BenchmarkDotNet.Attributes;
using FakeItEasy;
using Imposter.Abstractions;
using Mockolate;
using Mockolate.Verify;
using Moq;
using NSubstitute;

Expand Down Expand Up @@ -42,6 +45,58 @@ public void TUnitMocks_FullWorkflow()
loggerMock.Log(TUnitArg.Any<string>(), TUnitArg.Any<string>()).WasCalled(Times.Once);
}

[Benchmark(Description = "Imposter")]
public void Imposter_FullWorkflow()
{
// Create
var repoImposter = IUserRepository.Imposter();
var loggerImposter = ILogger.Imposter();

// Setup
repoImposter.GetById(1).Returns(new User { Id = 1, Name = "Alice", Email = "alice@test.com" });
repoImposter.Exists(1).Returns(true);
loggerImposter.IsEnabled(Arg<string>.Any()).Returns(true);

// Invoke
var repo = repoImposter.Instance();
var logger = loggerImposter.Instance();
var user = repo.GetById(1);
var exists = repo.Exists(1);
logger.Log("INFO", $"User {user!.Name} exists: {exists}");
repo.Save(new User { Id = 2, Name = "Bob" });

// Verify
repoImposter.GetById(1).Called(Count.Once());
repoImposter.Exists(1).Called(Count.Once());
repoImposter.Save(Arg<User>.Any()).Called(Count.Once());
loggerImposter.Log(Arg<string>.Any(), Arg<string>.Any()).Called(Count.Once());
}

[Benchmark(Description = "Mockolate")]
public void Mockolate_FullWorkflow()
{
// Create
var repo = IUserRepository.CreateMock();
var logger = ILogger.CreateMock();

// Setup
repo.Mock.Setup.GetById(1).Returns(new User { Id = 1, Name = "Alice", Email = "alice@test.com" });
repo.Mock.Setup.Exists(1).Returns(true);
logger.Mock.Setup.IsEnabled(Mockolate.It.IsAny<string>()).Returns(true);

// Invoke
var user = repo.GetById(1);
var exists = repo.Exists(1);
logger.Log("INFO", $"User {user!.Name} exists: {exists}");
repo.Save(new User { Id = 2, Name = "Bob" });

// Verify
repo.Mock.Verify.GetById(1).Once();
repo.Mock.Verify.Exists(1).Once();
repo.Mock.Verify.Save(Mockolate.It.IsAny<User>()).Once();
logger.Mock.Verify.Log(Mockolate.It.IsAny<string>(), Mockolate.It.IsAny<string>()).Once();
}

[Benchmark(Description = "Moq")]
public void Moq_FullWorkflow()
{
Expand All @@ -52,7 +107,7 @@ public void Moq_FullWorkflow()
// Setup
repoMock.Setup(x => x.GetById(1)).Returns(new User { Id = 1, Name = "Alice", Email = "alice@test.com" });
repoMock.Setup(x => x.Exists(1)).Returns(true);
loggerMock.Setup(x => x.IsEnabled(It.IsAny<string>())).Returns(true);
loggerMock.Setup(x => x.IsEnabled(Moq.It.IsAny<string>())).Returns(true);

// Invoke
var repo = repoMock.Object;
Expand All @@ -66,8 +121,8 @@ public void Moq_FullWorkflow()
// Verify
repoMock.Verify(x => x.GetById(1), Moq.Times.Once());
repoMock.Verify(x => x.Exists(1), Moq.Times.Once());
repoMock.Verify(x => x.Save(It.IsAny<User>()), Moq.Times.Once());
loggerMock.Verify(x => x.Log(It.IsAny<string>(), It.IsAny<string>()), Moq.Times.Once());
repoMock.Verify(x => x.Save(Moq.It.IsAny<User>()), Moq.Times.Once());
loggerMock.Verify(x => x.Log(Moq.It.IsAny<string>(), Moq.It.IsAny<string>()), Moq.Times.Once());
}

[Benchmark(Description = "NSubstitute")]
Expand Down
7 changes: 7 additions & 0 deletions TUnit.Mocks.Benchmarks/ImposterRegistrations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Imposter.Abstractions;
using TUnit.Mocks.Benchmarks;

[assembly: GenerateImposter(typeof(INotificationService))]
[assembly: GenerateImposter(typeof(ILogger))]
[assembly: GenerateImposter(typeof(IUserRepository))]
[assembly: GenerateImposter(typeof(ICalculatorService))]
69 changes: 66 additions & 3 deletions TUnit.Mocks.Benchmarks/InvocationBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using FakeItEasy;
using Imposter.Abstractions;
using Mockolate;
using Moq;
using NSubstitute;

Expand All @@ -15,6 +16,9 @@ public class InvocationBenchmarks
private Mock<ICalculatorService>? _tunitMock;
private ICalculatorService? _tunitObject;
private Moq.Mock<ICalculatorService>? _moqMock;
private ICalculatorServiceImposter? _imposterMock;
private ICalculatorService? _imposterObject;
private ICalculatorService? _mockolateObject;
private ICalculatorService? _moqObject;
private ICalculatorService? _nsubObject;
private ICalculatorService? _fakeObject;
Expand All @@ -28,10 +32,21 @@ public void Setup()
_tunitMock.Format(TUnitArg.Any<int>()).Returns("formatted");
_tunitObject = _tunitMock.Object;

// Imposter
_imposterMock = ICalculatorService.Imposter();
_imposterMock.Add(Arg<int>.Any(), Arg<int>.Any()).Returns(42);
_imposterMock.Format(Arg<int>.Any()).Returns("formatted");
_imposterObject = _imposterMock.Instance();

// Mockolate
_mockolateObject = ICalculatorService.CreateMock();
_mockolateObject.Mock.Setup.Add(Mockolate.It.IsAny<int>(), Mockolate.It.IsAny<int>()).Returns(42);
_mockolateObject.Mock.Setup.Format(Mockolate.It.IsAny<int>()).Returns("formatted");

// Moq
_moqMock = new Moq.Mock<ICalculatorService>();
_moqMock.Setup(x => x.Add(It.IsAny<int>(), It.IsAny<int>())).Returns(42);
_moqMock.Setup(x => x.Format(It.IsAny<int>())).Returns("formatted");
_moqMock.Setup(x => x.Add(Moq.It.IsAny<int>(), Moq.It.IsAny<int>())).Returns(42);
_moqMock.Setup(x => x.Format(Moq.It.IsAny<int>())).Returns("formatted");
_moqObject = _moqMock.Object;

// NSubstitute
Expand All @@ -51,6 +66,18 @@ public int TUnitMocks_Invoke()
return _tunitObject!.Add(1, 2);
}

[Benchmark(Description = "Imposter")]
public int Imposter_Invoke()
{
return _imposterObject!.Add(1, 2);
}

[Benchmark(Description = "Mockolate")]
public int Mockolate_Invoke()
{
return _mockolateObject!.Add(1, 2);
}

[Benchmark(Description = "Moq")]
public int Moq_Invoke()
{
Expand All @@ -75,6 +102,18 @@ public string TUnitMocks_InvokeString()
return _tunitObject!.Format(42);
}

[Benchmark(Description = "Imposter (String)")]
public string Imposter_InvokeString()
{
return _imposterObject!.Format(42);
}

[Benchmark(Description = "Mockolate (String)")]
public string Mockolate_InvokeString()
{
return _mockolateObject!.Format(42);
}

[Benchmark(Description = "Moq (String)")]
public string Moq_InvokeString()
{
Expand Down Expand Up @@ -105,6 +144,30 @@ public int TUnitMocks_ManyInvocations()
return sum;
}

[Benchmark(Description = "Imposter (100 calls)")]
public int Imposter_ManyInvocations()
{
var sum = 0;
for (var i = 0; i < 100; i++)
{
sum += _imposterObject!.Add(i, i);
}

return sum;
}

[Benchmark(Description = "Mockolate (100 calls)")]
public int Mockolate_ManyInvocations()
{
var sum = 0;
for (var i = 0; i < 100; i++)
{
sum += _mockolateObject!.Add(i, i);
}

return sum;
}

[Benchmark(Description = "Moq (100 calls)")]
public int Moq_ManyInvocations()
{
Expand Down
31 changes: 30 additions & 1 deletion TUnit.Mocks.Benchmarks/MockCreationBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using BenchmarkDotNet.Attributes;
using FakeItEasy;
using Imposter.Abstractions;
using Mockolate;
using Moq;
using NSubstitute;
using TUnit.Mocks;

namespace TUnit.Mocks.Benchmarks;

Expand All @@ -19,6 +20,20 @@ public object TUnitMocks_CreateMock()
return mock.Object;
}

[Benchmark(Description = "Imposter")]
public object Imposter_CreateMock()
{
var imposter = ICalculatorService.Imposter();
return imposter.Instance();
}

[Benchmark(Description = "Mockolate")]
public object Mockolate_CreateMock()
{
var sut = ICalculatorService.CreateMock();
return sut;
}

[Benchmark(Description = "Moq")]
public object Moq_CreateMock()
{
Expand Down Expand Up @@ -47,6 +62,20 @@ public object TUnitMocks_CreateMock_Repository()
return mock.Object;
}

[Benchmark(Description = "Imposter (Repository)")]
public object Imposter_CreateMock_Repository()
{
var imposter = IUserRepository.Imposter();
return imposter.Instance();
}

[Benchmark(Description = "Mockolate (Repository)")]
public object Mockolate_CreateMock_Repository()
{
var sut = IUserRepository.CreateMock();
return sut;
}

[Benchmark(Description = "Moq (Repository)")]
public object Moq_CreateMock_Repository()
{
Expand Down
Loading
Loading