Skip to content

Quickstart

This walks through a full (if tiny) Mokkit test — with xUnit and NSubstitute in C#, with testing and a hand-rolled fake in Go. See Installation for the packages.

A service with one dependency we’ll want to stand in for:

public interface IEmailSender
{
Task SendWelcome(string address);
}
public sealed class SignupService(IEmailSender email)
{
public async Task<Guid> Register(string address)
{
await email.SendWelcome(address);
return Guid.NewGuid();
}
}

The Stage is where your services live during a test. Here we use the dependency-free Bag container to hold a double and the service under test — the double is reachable both under its own type (to arrange and observe it) and behind the interface the subject receives:

using Mokkit.Containers.Bag;
using Mokkit.Suite;
using NSubstitute;
public sealed class SignupTests
{
private static async Task<TestStage> NewStage()
{
var email = Substitute.For<IEmailSender>();
var setup = await TestStageSetup.Create(
new BagContainerBuilder()
.AddInstance(email)
.AddInstance(new SignupService(email)));
return setup.EnterStage();
}
}

An Inspect verb observes an outcome. This one reads “a welcome email was sent to…”:

In C#, vocabulary is extension methods:

using Mokkit.Inspect;
public static class SignupVocabulary
{
public static ITestInspect WelcomeEmailSent(this ITestInspect inspect, string toAddress) =>
inspect.Then(host => host.Execute<IEmailSender>(email =>
email.Received(1).SendWelcome(toAddress)));
}

Now the test reads as Arrange → Act → Inspect. (This one needs no arrange.)

[Fact]
public async Task Registering_a_user_sends_a_welcome_email()
{
var stage = await NewStage();
// ACT — the Act phase resolves the service, runs the one thing under test, and returns its result.
var id = await stage.Act().Returning(host =>
host.ExecuteAsync<SignupService, Guid>(service => service.Register("acme@example.com")));
// INSPECT — observe the outcome through your vocabulary.
await stage.Inspect()
.WelcomeEmailSent("acme@example.com");
Assert.NotEqual(Guid.Empty, id);
}
  • Composing (TestStageSetup.Create(...) / mokkit.NewSetup(...)) built your containers once; entering a stage gave the test a fresh, isolated world.
  • The Act phase resolved the service from the stage, ran the one thing under test, and handed back its result.
  • Your Inspect verb resolved the same double from the stage and observed the call.

The verb WelcomeEmailSent is the seed of your project’s vocabulary. As you add Arrange verbs (to set up state) and more Inspect verbs (to observe it), tests become short, readable compositions of sentences — with full IDE and compile-time support.