Skip to content

Feature request: assertion helper for "a tapped request had a JSON body like..." #38

Description

@jwadhams

Context

A recurring pattern in consumer test suites (found while reviewing services/incentives's LexusIncentivesServiceTest) is: find the one GuzzleTapper-captured request matching a method+URL, decode its JSON body, and assert on specific fields — to prove the actual outbound request carried the right data, not just that a mocked response was returned correctly.

Current code to do this (4 lines, every time):

$offersCall = $tapper->getCalls()
    ->first(fn ($request) => str_contains((string) $request->getUri(), 'inventoryservices.lexusdealerdigital.com'));
$this->assertNotNull($offersCall, 'Expected a call to the Lexus offers API.');
$sentBody = json_decode((string) $offersCall->getBody(), true);
$this->assertSame('08052', $sentBody['zip'], 'Zip sent to Lexus must come from Customer API, not the request.');

Proposal

Add a helper to Carsdotcom\ApiRequest\Testing\RequestClassAssertions (the existing trait that already holds assertRequestCacheBodyContains), something like:

protected static function assertTapperSentJsonBodyLike(
    GuzzleTapper $tapper,
    string $method,
    string $urlPattern,
    array $expectedBodySubset,
    string $message = '',
): void
  • Reuses GuzzleTapper::getCalls() and the same preg_match($urlPattern, ...) matching convention GuzzleTapper::getCountLike() already uses, so behavior stays consistent with the rest of the class.
  • Fails clearly if no request matched method+urlPattern at all (distinct from "matched, but body was wrong").
  • Asserts $expectedBodySubset as a subset of the decoded JSON body (like assertArraySubset/Laravel's assertJson), not an exact match — so a caller only pins down the field(s) they actually care about.

Collapses the 4-line pattern above to:

$this->assertTapperSentJsonBodyLike(
    $tapper,
    'POST',
    '#inventoryservices\.lexusdealerdigital\.com#',
    ['zip' => '08052'],
    'Zip sent to Lexus must come from Customer API, not the request.',
);

Happy to put up a PR with this if the shape looks right — mostly wanted to check the API design before writing it, since it needs to fit alongside GuzzleTapper's existing getCountLike()/getCount() conventions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions