Skip to main content

Introduction

The Sandbox package includes FakeSandbox, a test double that implements the same CanExecuteCommand interface as all real drivers. It lets you write fast, deterministic tests for code that depends on sandbox execution — without spawning any processes, pulling container images, or requiring any system binaries. FakeSandbox supports canned responses, FIFO queuing for repeated commands, a default fallback response, array-based response definitions, command recording, streaming callback simulation, and custom policies.

Creating a Fake

The fromResponses() Factory

The quickest way to create a mock is with the fromResponses() static factory. Pass an associative array where keys are the expected command strings and values are lists of ExecResult objects to return in order:
The command key is formed by joining the argv array with spaces: ['php', '-v'] becomes 'php -v'. Make sure the key in your response map matches exactly.

The Constructor

For more control, use the constructor directly. This lets you specify a custom ExecutionPolicy:
The fromResponses() factory uses ExecutionPolicy::default() when no policy is specified.

Queueing Multiple Responses

When the same command is called multiple times, provide multiple results in the list. They are consumed in FIFO order — each call to execute() shifts the next response off the queue:
If the queue is exhausted and no default response is set, the next call throws a RuntimeException.

Default Response

To provide a fallback for any command that does not have a specific canned response, pass a defaultResponse:
The default response is also used when a command’s specific queue has been exhausted.

Enqueuing Responses After Construction

You can add responses to an existing fake at any time using the enqueue() method. This is useful in test setups where you build the fake incrementally:

Array-Based Responses

For convenience, you can define responses as associative arrays instead of ExecResult objects. The mock normalizes them automatically:
The recognized keys match the ExecResult::toArray() format: Any omitted key uses its default value, so you only need to specify the fields relevant to your test.

Inspecting Recorded Commands

The mock records every command it receives. Use the commands() method to retrieve the full history:
This is useful for asserting that your code called the expected commands in the expected order.

Standard Input Recording

When stdin is provided, it is appended to the recorded argv as a [stdin=...] entry:

Streaming Callback Support

The FakeSandbox honors the streaming callback, just like real drivers. When a callback is provided, the fake delivers stdout and stderr from the canned response as single chunks:
Empty stdout or stderr is not delivered to the callback, matching the behavior of real drivers.

Testing Failure Scenarios

Simulating Timeouts

Create an ExecResult with timedOut: true and exit code 124:

Simulating Truncated Output

Set the truncation flags to test how your code handles oversized output:

Simulating Command Failures

Test error handling by returning non-zero exit codes:

Using FakeSandbox with Dependency Injection

The FakeSandbox implements CanExecuteCommand, so it can be injected anywhere a real sandbox is expected. This is the recommended approach for testing application services:

Quick Reference