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
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