pact-foundation/pact-php
PHP implementation of the Pact consumer-driven contract testing framework. Define contracts between services, run provider verification, and integrate with PHPUnit/CI to prevent breaking API changes. Supports HTTP interactions, mock servers, and Pact Broker workflows.
Illuminate\Http\Client, Route::get(), etc.) and can mock external services (e.g., APIs, queues) during unit/integration tests.PHPUnit, Pest) but operates at a higher level of abstraction.Http::fake() for cross-service interactions.given(), willRespondWith() for stateful APIs).Bus or Events.artisan pact:verify command.config/pact.php or versioned alongside API specs (OpenAPI/Swagger).| Risk Area | Mitigation Strategy |
|---|---|
| Test Flakiness | Pact’s strict matching may expose overly rigid contracts. Use generous matching (e.g., regex, wildcards) where appropriate. |
| Performance Overhead | Mock servers add latency. Use parallel test execution (e.g., Pest’s --parallel) and cache contracts to avoid regeneration. |
| Tooling Ecosystem | Limited Laravel-specific docs. Requires familiarity with Pact’s broader ecosystem (e.g., Pact Broker for contract storage). |
| State Management | Complex state transitions (e.g., multi-step workflows) may need custom providers or Laravel’s DatabaseTransactions. |
| Version Skew | Contracts must align with API versions. Use semantic versioning for contracts and automate version checks in CI. |
Http::fake() entirely, or supplement it for cross-service tests?Http::get(), Http::post(), etc., replacing Laravel’s Http::fake() for external calls.Route::get() with Pact’s DSL to define expected routes in tests.App\Providers\PactServiceProvider or test suites.@pact annotations or custom test traits.Illuminate\Queue interactions using Pact’s async DSL.Http::fake() calls with Pact for that service.pact-foundation/pact-php via Composer.phpunit.xml or pest.php.// config/pact.php
return [
'mock_service' => [
'host' => 'localhost',
'port' => 1234,
],
'provider' => [
'name' => 'laravel-service',
'broker' => env('PACT_BROKER_URL'),
],
];
tests/Features/Pact/ApiConsumerTest.php).$pact = new Consumer('laravel-consumer', 'v1');
$pact->given('a user exists')
->uponReceiving('a GET request to /users/{id}')
->withRequest('GET', '/users/123')
->willRespondWith(200, ['id' => 123, 'name' => 'John Doe']);
// app/Console/Commands/VerifyPact.php
use Pact\Verifier\Verifier;
public function handle() {
$verifier = new Verifier();
$verifier->verifyProvider(
new Provider('laravel-service'),
['tests/Features/Pact/pacts']
);
}
php artisan pact:verify
Contract Definition → Consumer Implementation → Contract Verification.Contract Definition (by consumer) → Provider Implementation → Pact Verification.pact:verify in a separate CI job (e.g., after merge to main).v1, v2) to manage breaking changes.deprecated: true flag to contracts in the Broker.pact-cli publish tests/Features/Pact/pacts --broker-base-url=$PACT_BROKER_URL
Expected: { "status": "success" }
Actual: { "status": "error", "message": "..." }
--verbose flag for mock server logs./users contract").tests/Features/Pact/TemplateTest.php).How can I help you explore Laravel packages today?