Scenarios
Scenarios let you define multiple sets of setups on a single mock and switch between them at runtime. This is useful
when the collaborator behaves differently depending on its internal state — for example a connection that starts
disconnected, becomes connected after Connect(), and times out after a failure.
A mock always has an active scenario (the empty string "" by default). When a member is accessed, Mockolate looks
for a matching setup in the active scenario first, then falls back to the default scope.
Defining scenarios
Use InScenario(name) to scope setups to a named scenario. It returns a scope whose Setup property mirrors
sut.Mock.Setup but targets the scenario's bucket:
sut.Mock.InScenario("disconnected").Setup.Ping().Throws<TimeoutException>();
sut.Mock.InScenario("connected").Setup.Ping().Returns(true);
A callback overload batches multiple setups into the same scenario:
sut.Mock.InScenario("connected", scope =>
{
scope.Setup.Ping().Returns(true);
scope.Setup.Send(It.IsAny<string>()).Returns(true);
});
Setups registered via InScenario do not leak into the default scope.
Switching scenarios
Chain .TransitionTo(name) on any method, property, indexer, or event subscription/unsubscription setup to change
the active scenario when the setup fires. The transition runs as a parallel side-effect — it does not replace
the return value or throw behaviour.
sut.Mock.InScenario("disconnected")
.Setup.Connect()
.Returns(true)
.TransitionTo("connected");
sut.Mock.InScenario("connected")
.Setup.Ping()
.Throws<TimeoutException>()
.TransitionTo("disconnected");
You can also change the active scenario manually via sut.Mock.TransitionTo("connected");, which is useful for
arranging the starting state.
Resolution rules
When dispatching a call, Mockolate looks up setups in this order:
- The active scenario's bucket (if non-empty).
- The default bucket (setups registered via
sut.Mock.Setup.*). - The mock's default behaviour.
Scenario setups add to, rather than replace, the default scope — register catch-alls in the default scope and override specific members per scenario.