Skip to content

UnderstudyPHPUnitIntegration ​

Rasuvaeff\Understudy\PhpUnit\UnderstudyPHPUnitIntegration

Trait — Package: rasuvaeff/understudy-phpunit — Source — Version: v1.0.0

Ends every PHPUnit test with understudy's own bookkeeping done for it.

php
final class CheckoutTest extends TestCase
{
    use UnderstudyPHPUnitIntegration;

public function testChargesForTheCart(): void
    {
        $books = Understudy::for(BookRepositoryInterface::class);
        expect(fn () => $books->find(7))->returns($expected = new Book(7));

$receipt = (new Checkout($books))->charge([7]);

self::assertSame($expected->price, $receipt->total);
    }
}

One registration says both things: find(7) must be called exactly once, and it answers $expected. Two rules of the engine decide that shape, and this snippet used to break both:

  • Arm before the run. An expect() counts only the calls that arrive after it is declared. Written below the action it counts zero and fails as "called never" about a call that did happen; to claim a call that has already happened, use verify().
  • One registration per call. A when() stub and an expect() naming the same call are two registrations of one call, and the engine answers with ConflictingExpectation.

Kept in step with the README's Usage section and examples/readme-usage.php, which runs it; DocumentedUsageTest fails when the three drift apart.

On a test that reached PHPUnit\Framework\TestCase::assertPostConditions() — that is, passed its body — the whole context is verified: an expect() the code never fulfilled fails the test as an assertion failure. A test whose body threw keeps its own exception untouched; verification would only mask the error that actually happened. Either way the context is reset, so nothing leaks into the next test.

A base class may flip strict stubbing for a whole project by overriding PhpUnit\understudyStrictStubs().

If the class also overrides assertPostConditions() itself, PHP resolves the conflict silently in favour of the class — the trait's verification would stop running without any error. Compose explicitly instead:

php
use Rasuvaeff\Understudy\PhpUnit\UnderstudyPHPUnitIntegration {
    UnderstudyPHPUnitIntegration::assertPostConditions
        as understudyAssertPostConditions;
}

protected function assertPostConditions(): void
{
    // your post-conditions ...
    $this->understudyAssertPostConditions();
}

The user's post-conditions run first — the check closer to the test body wins, same as the README says.

No public members beyond what is documented above.