6.9 KiB
Testing with Mollie API Client
Test Mode Configuration
Key Concepts
- Test mode is automatically determined by API key prefix (
test_orlive_) - Explicit
testmodeparameter available for OAuth scenarios - Configure at global client level or per individual request
Global Configuration
use Mollie\Api\MollieApiClient;
$mollie = new MollieApiClient();
$mollie->setApiKey("test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM");
$mollie->test(true); // Applies to all subsequent requests
Per-Request Configuration
// Payment request with test mode
$createPaymentRequest = new CreatePaymentRequest(/* ... */);
$mollie->send($createPaymentRequest->test(true));
// Endpoint collection example
$customer = $mollie->customers->get('cust_12345678', testmode: true);
API Mocking
Basic Usage
API responses can be simulated without network calls by using the MollieApiClient::fake() method. Each Request/Response pair passed to the fake method is consumed after a matching request.
Note
To keep pairs available for reuse after they've been matched, use the
retainRequestsparameter:MollieApiClient::fake([...], retainRequests: true)
use Mollie\Api\MollieApiClient;
use Mollie\Api\Fake\MockResponse;
use Mollie\Api\Http\Requests\GetPaymentRequest;
$client = MollieApiClient::fake([
GetPaymentRequest::class => new MockResponse(
body: [
'resource' => 'payment',
'id' => 'tr_xxxxxxxxxxxx',
'mode' => 'test',
'amount' => [
'value' => '20.00',
'currency' => 'EUR'
],
'description' => 'Test',
'status' => 'open',
// ...
],
status: 200
)
]);
$payment = $client->send(new GetPaymentRequest('tr_xxxxxxxxxxxx'));
Sequence Mock Responses
To return different responses for the same request type, use SequenceMockResponse and pass MockResponse or Closure (which return MockResponse instances) in the order they should occur.
$client = MollieApiClient::fake([
DynamicGetRequest::class => new SequenceMockResponse(
MockResponse::ok(['first' => 'response']),
MockResponse::ok(['second' => 'response']),
function (PendingRequest $pendingRequest) {
//...
return MockResponse::ok(['third' => 'response']);
}
)
])
To verify that a request was sent, use `assertSent` or `assertSentCount`.
```php
$client->send(new GetPaymentRequest('tr_xxxxxxxxxxxx', embedRefunds: true));
$client->assertSent(GetPaymentRequest::class);
$client->assertSent(function (PendingRequest $pendingRequest, Response $response) {
return $pendingRequest->query()->get('embed') === 'refunds';
});
$client->assertSentCount(1);
MockResponse Options
Configure responses using:
- Arrays: Direct data structure
- Strings: JSON payloads or predefined fixture names
- Callables: Dynamic response generation or intercepting assertions
// Array response
MockResponse::created([
'id' => 'tr_xxxxxxxxxxxx',
'amount' => ['value' => '20.00', 'currency' => 'EUR']
]);
// Fixture response
MockResponse::created('payment');
// Dynamic response
MockResponse::created(function (PendingRequest $request) {
return ['amount' => $request->hasParameter('amount') ? 10 : 20];
});
// Intercepting assertions
function (PendingRequest $request) use ($idempotencyKey) {
$this->assertEquals($idempotencyKey, $request->headers()->get('Idempotency-Key'));
return MockResponse::created('payment');
}
Working with Collections
Create paginated list responses:
use Mollie\Api\Resources\PaymentCollection;
$client = MollieApiClient::fake([
GetPaginatedPaymentsRequest::class => MockResponse::list(PaymentCollection::class)
->add([
'resource' => 'payment',
'id' => 'tr_xxxxxxxxxxxx',
'mode' => 'test',
'amount' => [
'value' => '20.00',
'currency' => 'EUR'
],
'description' => 'Test',
'status' => 'open',
// ...
])
->create()
]);
Handling Embedded Resources
Simulate HAL+JSON embedded resources using the _embedded property:
Key Concepts
- Use
MockResponse::resource()to start building a resource response - Chain
embed()calls to add related collections - Maintain resource relationships with a fluent interface
use Mollie\Api\Resources\Payment;
use Mollie\Api\Resources\RefundCollection;
use Mollie\Api\Resources\ChargebackCollection;
$client = MollieApiClient::fake([
GetPaymentRequest::class => MockResponse::resource(Payment::class)
->with([ // Main resource properties
'resource' => 'payment',
'id' => 'tr_xxxxxxxxxxxx',
'amount' => [
'value' => '20.00',
'currency' => 'EUR'
]
])
->embed(RefundCollection::class) // First embedded collection
->add([
'resource' => 'refund',
'id' => 're_12345',
'amount' => [
'value' => '10.00',
'currency' => 'EUR'
]
])
->embed(ChargebackCollection::class) // Second embedded collection
->add([
'resource' => 'chargeback',
'id' => 'chb_12345',
'amount' => [
'value' => '20.00',
'currency' => 'EUR'
]
])
->create()
]);
// Resulting response will contain:
// - Payment details in main body
// - Refunds in _embedded.refunds
// - Chargebacks in _embedded.chargebacks
Error Response Mocking
Simulate API error responses using dedicated helper methods or the generic error builder:
Common Error Shortcuts
use Mollie\Api\Fake\MockResponse;
// 404 Not Found
$client = MollieApiClient::fake([
GetPaymentRequest::class => MockResponse::notFound('No payment exists with token tr_xxxxxxxxxxx')
]);
// 422 Validation Error (with optional field reference)
$client = MollieApiClient::fake([
CreatePaymentRequest::class => MockResponse::unprocessableEntity(
detail: 'Amount must be at least €1.00',
field: 'amount'
)
]);
Generic Error Builder
// Custom status code example
$response = MockResponse::error(
status: 403,
title: 'Forbidden',
detail: 'Insufficient permissions to access this resource'
);
// Special characters handling
$detail = 'Invalid parameter "recurringType" - did you mean "sequenceType"?';
$response = MockResponse::unprocessableEntity($detail, 'field');
Error Response Structure All errors follow Mollie's standardized format:
{
"status": 404,
"title": "Not Found",
"detail": "No payment exists with token tr_xxxxxxxxxxx",
"field": "amount" // Only present for validation errors
}