Developer Tools
Testing
Test your integration without calling PayMongo. The package fakes its whole API and ships realistic fixture payloads; these examples run in the Playground's own test suite.
- Paymongo::fake() answers the endpoints the package calls from fixtures: creates echo the attributes you sent, retrievals echo the id you asked for. A path it does not know gets a PayMongo-style 404.
- Pass URL patterns to Paymongo::fake() to stub a specific response. Stubs win over the catch-all.
- Fixtures build full PayMongo payloads. Give them an explicit id so assertions stay deterministic, and wrap them in Fixtures::list() with hasMore to fake pagination.
- Paymongo::assertSent() and Paymongo::assertNothingSent() inspect the requests the package made, and interoperate with Http::fake().
- Error responses map to typed exceptions, so a stubbed 402 surfaces as PaymentDeclinedException just as a real decline would.
tests/Feature/PaymongoFakeExamplesTest.php
PHP
<?php
/*
* These tests are shown on the Playground's Developer Tools "Testing" page as
* examples of testing an integration with the package's fake and fixtures.
* They run in this suite, so the examples a Visitor copies are known to pass.
*/
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Sleep;
use Luigel\Paymongo\Data\Refund;
use Luigel\Paymongo\Exceptions\PaymentDeclinedException;
use Luigel\Paymongo\Facades\Paymongo;
use Luigel\Paymongo\Testing\Fixtures;
it('fakes the whole PayMongo API and asserts on the request sent', function () {
Paymongo::fake();
$intent = Paymongo::paymentIntents()->create([
'amount' => 10000,
'currency' => 'PHP',
'payment_method_allowed' => ['card'],
]);
expect($intent->amount)->toBe(10000);
Paymongo::assertSent(fn (Request $request): bool => $request->url() === 'https://api.paymongo.com/v1/payment_intents'
&& $request['data']['attributes']['amount'] === 10000);
});
it('stubs one endpoint with a fixture that has an explicit id', function () {
Paymongo::fake([
'api.paymongo.com/v1/payments/*' => Http::response(Fixtures::payment([
'id' => 'pay_known_id',
'status' => 'paid',
])),
]);
$payment = Paymongo::payments()->retrieve('pay_known_id');
expect($payment->id)->toBe('pay_known_id')
->and($payment->status?->value)->toBe('paid');
});
it('surfaces a declined card as a typed exception', function () {
Paymongo::fake([
'api.paymongo.com/v1/payment_intents/*/attach' => Http::response([
'errors' => [['code' => 'card_declined', 'detail' => 'Your card was declined.']],
], 402),
]);
Paymongo::paymentIntents()->attach('pi_test', 'pm_test');
})->throws(PaymentDeclinedException::class, 'Your card was declined.');
it('walks every page of a list lazily', function () {
Paymongo::fake([
'api.paymongo.com/v1/refunds?limit=2' => Http::response(Fixtures::list([
Fixtures::refund(['id' => 'ref_1']),
Fixtures::refund(['id' => 'ref_2']),
], hasMore: true)),
'api.paymongo.com/v1/refunds?limit=2&after=ref_2' => Http::response(Fixtures::list([
Fixtures::refund(['id' => 'ref_3']),
])),
]);
$ids = Paymongo::refunds()->list(['limit' => 2])
->lazy()
->map(fn (Refund $refund): string => $refund->id)
->all();
expect($ids)->toBe(['ref_1', 'ref_2', 'ref_3']);
});
it('retries a rate-limited request after the Retry-After delay', function () {
Sleep::fake();
Paymongo::fake([
'api.paymongo.com/v1/payments/*' => Http::sequence()
->push(['errors' => [['code' => 'rate_limited', 'detail' => 'Too many requests.']]], 429, ['Retry-After' => '2'])
->push(Fixtures::payment(['id' => 'pay_after_retry'])),
]);
$payment = Paymongo::payments()->retrieve('pay_after_retry');
expect($payment->id)->toBe('pay_after_retry');
Sleep::assertSleptTimes(1);
Sleep::assertSequence([Sleep::for(2)->seconds()]);
});