sbergen / GenSubstitute

GenSubstitute is a C# source generator based mocking library
MIT License
2 stars 0 forks source link

GenSubstitute

GenSubstitute is a C# source generator based mocking library.

It's still fairly early in its development, so while feedback and bug reports are extremely welcome, use at your own risk!

Installation

.NET projects

Get from NuGet in your IDE, or use

dotnet add package GenSubstitute --version 0.1.0-alpha

Unity 2021.3 or newer

  1. Download UnityDlls.zip from the latest release.
  2. Add the .dll files into your Unity assets.
  3. Optionally add the .pdb files next to the dlls for debug symbols.
  4. Reference GenSubstitute.Runtime.dll from your test project.
  5. Set up GenSubstitute.SourceGenerator.Unity.dll as a source generator, as outlined in the Unity instructions.

Examples

You can compare these with the NSubstitute examples.

Basic usage

// Create:
var calculator = Gen.Substitute<ICalculator>().Create();

// Set a return value:
calculator.SetUp.Add(1, 2).Returns(3);
Assert.Equal(3, calculator.Object.Add(1, 2));

// Configure a method with a lambda
calculator.SetUp.Add(Arg.Any, Arg.Any).As((a, b) => a + b);
Assert.Equal(42, calculator.Object.Add(40, 2));

// Check received calls and arguments:
calculator.Received.Add(1, Arg.Any).Once();
calculator.Received.Add(2, 2).Never();
Assert.Equal(40, calculator.Received.Add(Arg.Any, Arg.Any)[1].Arg1);

// Raise events
calculator.Raise.PoweringUp();

Helpful exceptions

ReceivedCallsAssertionException: Expected to receive one call matching:
  System.Int32 ICalculator.Add(1, any System.Int32)
Actually received:
  Int32 ICalculator.Add(40, 2)

Some prettifying of the error messages is on the TODO list.

Pros (compared to dynamically generated mocks)

Cons

Features

Implemented

Definitely on the TODO list

Will probably be added

Needs investigation

Hesitant to add

Kudos

Why a new library?

My main motivation for writing GenSubstitute was to support mocking in Unity IL2CPP builds, which can't use dynamic code generation. While there are some source generator based mocking libraries around, there were things about each I did not like, so I thought it would be fun to write my own. I also hope others find it useful!

I also believe there are things that can be done better with source generation compared to dynamic mocking. And when working on GenSubstitute, I've been trying to challenge my current ways of thinking about mocking, and think outside the box where possible - I'm willing to bet there are discoveries yet to be made!