Write Deterministic PHPUnit Assertions with Mockery::capture

Published: (March 2, 2026 at 08:39 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Problem

When a method internally generates a random value, its return value becomes unpredictable, making it hard to write deterministic assertions in tests.

class Hash
{
    public function make($data): string
    {
        return hash_hmac('sha256', $data, false);
    }
}

class RandomHash
{
    public function __construct(public Hash $hash)
    {
    }

    /**
     * @throws \Exception
     */
    public function hash(): string
    {
        $random = md5(random_int(1, 10));

        return $this->hash->make($random);
    }
}

Because random_int returns a different value on each call, the result of hash() changes each time, so a test cannot assert a fixed expected value.

class RandomHashTest extends TestCase
{
    public function test_mockery_capturing_arguments(): void
    {
        $hash = new Hash();
        $randomHash = new RandomHash($hash);

        // no way to write a definitive assertion here
        $actual = $randomHash->hash();
    }
}

Solution

Mockery’s capturing arguments feature can store the arguments passed to a method call. By combining it with passthru() (which lets the original method execute normally), you can capture the intermediate random value and then compute the expected result.

First, install Mockery as a development dependency:

composer require --dev mockery/mockery

Example Test

use Mockery;
use PHPUnit\Framework\TestCase;

class RandomHashTest extends TestCase
{
    /**
     * @throws \Exception
     */
    public function test_mockery_capturing_arguments(): void
    {
        // Create a spy for the Hash class
        $hash = Mockery::spy(new Hash());

        // Capture the intermediate random value; passthru lets make() run normally
        $hash->allows('make')
             ->with(Mockery::capture($random))
             ->passthru();

        $randomHash = new RandomHash($hash);

        $actual = $randomHash->hash();

        // Now $random is known, so we can compute the expected value
        self::assertEquals((new Hash)->make($random), $actual);
    }
}
0 views
Back to Blog

Related posts

Read more »