Skip to content

The Bag container

Not every test needs a DI framework. The Bag (Mokkit.Containers.Bag) is a trivial container that holds instances you hand it — no auto-wiring, no options, no dependency on Microsoft DI. It’s the right tool for two situations: your very first test, and a stage that just needs to hold some pre-built clients.

var setup = await TestStageSetup.Create(
new BagContainerBuilder()
.AddInstance(email) // a singleton you own; reused across resolves
.AddInstance(new SignupService(email))
.AddFactory(() => new DbContext(options))); // built fresh per stage, disposed with the stage
var stage = setup.EnterStage();
  • AddInstance(x) — stores the object as-is. The same instance is returned on every Execute<T>, and Mokkit does not dispose it (you own its lifetime). Ideal for a shared mock or HTTP client.
  • AddFactory(() => ...) — one instance per stage, created on first resolve and disposed when the stage is disposed. Ideal for a per-test DbContext.

Resolving is the same Execute/ExecuteAsync as any container:

stage.Execute<IEmailSender>(email => email.Received(1).SendWelcome(address));

A first test. Hand-wire a substitute and the service under test — the same substitute goes into both, so you can drive it and verify it, with zero container ceremony (this is the quickstart setup).

A stage of external clients. In the E2E suite, the whole system runs in Docker and the stage only needs to hold clients pointed at it — no mocks, no DI graph. Bag is a perfect fit:

var external = new BagContainerBuilder().UseInit(bag =>
{
bag.AddInstance(new HttpClient { BaseAddress = apiBaseAddress });
bag.AddInstance<IProducer<string, string>>(BuildKafkaProducer(bootstrap));
bag.AddInstance(new KafkaProbe(bootstrap));
bag.AddFactory(() => new ExampleContext(NpgsqlOptions(connectionString))); // fresh + disposed per stage
return Task.CompletedTask;
});

The moment you want to test a real object graph — a service whose dependencies are themselves resolved and constructed by a container — move up to a real DI adapter and bridge your mocks in. That’s the real DI container guide.