A contract test is a recorded response replayed

The response a shipped mobile client expects is a fact about the past, and the cheapest way to keep it true is to record one and replay it against the current code.

public function testTheV1OrderShapeIsUnchanged(): void
{
    $recorded = json_decode(
        file_get_contents(__DIR__ . '/contracts/order-2.1.0.json'), true
    );

    $live = $this->getJson('/api/v1/orders/1')->json();

    foreach ($recorded as $field => $value) {
        $this->assertArrayHasKey($field, $live);
        $this->assertSame(gettype($value), gettype($live[$field]));
    }
}

Asserting on presence and type rather than on value is what makes the test stable — the data changes and the shape must not. Recording the fixture when a client version ships means the file is dated evidence rather than somebody’s recollection of the contract. It catches exactly the class of change that breaks a client in the field, and it catches it in CI rather than in a crash report.