Matchers

phpspec ships with 30+ built-in matchers. All matchers support negation via not() and can be chained.

Quick reference

MatcherDescription
toBe($expected)Identity (===)
toBeLike($expected)Equality (==)
toBeTrue()Strictly true
toBeFalse()Strictly false
toBeNull()Strictly null
toBeEmpty()Empty string, array, or countable
toBeOfType($type)PHP type: 'string', 'int', 'float', etc.
toBeCallable()Value is callable
toBeAnInstanceOf($class)instanceof check
toContain($value)String or array contains value
toStartWith($prefix)String starts with prefix
toEndWith($suffix)String ends with suffix
toMatch($pattern)String matches regex
toHaveCount($n)Array/countable has n items
toHaveKey($key)Array has key
toBeGreaterThan($n)Numeric comparison
toBeLessThan($n)Numeric comparison
toHaveProperty($name)Object has public property
toThrow($class, $msg?)Callable throws exception

Identity matcher — toBe()

Strict comparison using ===:

expect(42)->toBe(42);
expect('hello')->toBe('hello');
expect(true)->toBe(true);

Equality matcher — toBeLike()

Loose comparison using ==:

expect('5')->toBeLike(5);
expect(0)->toBeLike(false);

Boolean matchers

expect(true)->toBeTrue();
expect(false)->toBeFalse();
expect(null)->toBeNull();
expect([])->toBeEmpty();

Type matchers

expect('hello')->toBeOfType('string');
expect(42)->toBeOfType('int');
expect(3.14)->toBeOfType('float');
expect(fn() => null)->toBeCallable();

Instance matcher

expect(new \stdClass())->toBeAnInstanceOf(\stdClass::class);
expect(new \RuntimeException('x'))->toBeAnInstanceOf(\Exception::class);

String matchers

expect('Hello, World!')->toContain('World');
expect('Hello, World!')->toStartWith('Hello');
expect('Hello, World!')->toEndWith('World!');
expect('abc123')->toMatch('/\d{3}/');

Collection matchers

expect([1, 2, 3])->toHaveCount(3);
expect([1, 2, 3])->toContain(2);
expect(['name' => 'Alice'])->toHaveKey('name');

Comparison matchers

expect(10)->toBeGreaterThan(5);
expect(3)->toBeLessThan(7);

Object property matcher

$obj = new \stdClass();
$obj->name = 'Alice';
expect($obj)->toHaveProperty('name');

Exception matcher

Pass a callable to expect():

expect(fn() => throw new \RuntimeException('boom'))
    ->toThrow(\RuntimeException::class);

// With message check
expect(fn() => throw new \RuntimeException('boom'))
    ->toThrow(\RuntimeException::class, 'boom');

Negation

Negate any matcher with not():

expect(5)->not()->toBe(3);
expect('hello')->not()->toBeEmpty();
expect([1, 2])->not()->toContain(99);
expect(42)->not()->toBeNull();

Custom matchers

Define your own matchers with addMatcher():

addMatcher(
    'toBeEven',
    fn($n) => $n % 2 === 0,
    'Expected %s to be even'
);

expect(4)->toBeEven();
expect(3)->not()->toBeEven();

For reusable matchers across specs, use Matcher Extensions.

Chained expectations

Chain multiple matchers on the same subject:

expect('hello')
    ->toBeOfType('string')
    ->toStartWith('h')
    ->toEndWith('o');