Installation Add the package via Composer:
composer require buero/pact-bundle
Register the bundle in config/app.php under extra.bundles:
Buero\PactBundle\PactBundle::class => ['all' => true],
Configuration Publish the default config:
php artisan vendor:publish --tag=pact-config
Update config/pact.php with your Pact Broker URL and consumer/provider details.
First Use Case: Consumer Contract Testing
Write a test in tests/Feature/PactTests:
use Buero\PactBundle\Tests\PactTestCase;
class MyServicePactTest extends PactTestCase
{
public function test_service_interaction()
{
$this->pact('my-service-provider')
->given('a valid request')
->expects()
->atLeastOne()
->get('/api/endpoint')
->willRespondWith(200, ['data' => 'test'])
->verify();
}
}
Run with:
php artisan pact:test
Define Provider Contracts Use annotations in provider code to document expected interactions:
/**
* @PactContract(
* name="my-service-provider",
* description="Handles user data requests"
* )
*/
class UserController extends Controller
{
// ...
}
Consumer-Driven Development
MyServicePactTest).php artisan pact:generate
Integration with CI
Add to .github/workflows/pact.yml:
- name: Pact Tests
run: php artisan pact:test
Http::pact() for Pact-aware requests:
$response = Http::pact('my-service-provider')->get('/endpoint');
Http calls with Pact mocks in tests:
$this->mockHttpClient()
->expects()
->get('https://external-api.com')
->willRespondWith(200, ['mocked' => 'data']);
$this->pact(config('services.pact.consumer_name'));
State Management
given() before expectations leads to silent failures.given() before expects() in tests.Provider Stub Generation
pact/stubs/ after generation.--force flag to regenerate stubs:
php artisan pact:generate --force
Broker Authentication
config/pact.php can cause security issues.env() or vault integration:
'broker' => [
'url' => env('PACT_BROKER_URL'),
'token' => env('PACT_BROKER_TOKEN'),
],
Test Isolation
--parallel flag:
php artisan pact:test --parallel
config/pact.php:
'debug' => env('APP_DEBUG', false),
storage/logs/pact.log for interaction details.php artisan pact:validate to check stubs against the broker.Custom Matchers
Extend Buero\PactBundle\Matchers\MatcherInterface for domain-specific assertions:
class CustomMatcher implements MatcherInterface
{
public function matches($expected, $actual): bool
{
// Custom logic
}
}
Register in config/pact.php:
'matchers' => [
CustomMatcher::class,
],
Provider Verification
Override PactBundle\Providers\ProviderVerifier to add custom verification steps:
class CustomVerifier extends ProviderVerifier
{
protected function verifyInteraction($interaction)
{
// Custom logic
parent::verifyInteraction($interaction);
}
}
Bind in AppServiceProvider:
$this->app->bind(
ProviderVerifier::class,
CustomVerifier::class
);
Event Listeners
Listen for pact.generated or pact.verified events to trigger post-processing:
use Buero\PactBundle\Events\PactGenerated;
public function handlePactGenerated(PactGenerated $event)
{
// Example: Upload stubs to S3
}
How can I help you explore Laravel packages today?