Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phiremock Client Laravel Package

mcustiel/phiremock-client

PHP client for Phiremock Server with a fluent API to define HTTP expectations, manage scenarios, and reset server state. Works with Guzzle 6 by default, or any PSR-18 HTTP client by overriding the factory for custom connections.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer (add to require-dev):
    composer require-dev mcustiel/phiremock-client guzzlehttp/guzzle
    
  2. Initialize the client in a test setup file (e.g., tests/TestCase.php):
    use Mcustiel\Phiremock\Client\Factory;
    use Mcustiel\Phiremock\Client\Connection\{Host, Port};
    
    protected function createPhiremockClient(): PhiremockClient
    {
        return Factory::createDefault()
            ->createPhiremockClient(new Host('localhost'), new Port('8080'));
    }
    

First Use Case: Mocking an API Endpoint

// In a test method
$client = $this->createPhiremockClient();
$client->createExpectation(
    on(getRequest('/api/users'))
        ->then(respond(200)->andBody('{"id": 1, "name": "Test User"}'))
);

Implementation Patterns

1. Fluent Expectation Chaining

Use the fluent interface for complex expectations:

$client->createExpectation(
    on(
        getRequest('/api/orders/{id}')
            ->andMethod(isEqualTo('POST'))
            ->andHeader('Authorization', contains('Bearer'))
            ->andBody(contains('{"status": "pending"}'))
    )->then(
        respond(201)
            ->andHeader('Location', contains('/api/orders/'))
            ->andBody('{"id": 2, "status": "created"}')
    )
);

2. Scenario-Driven Testing

Leverage scenarios for multi-step workflows:

// Setup
$client->createExpectation(
    on(getRequest('/api/login'))
        ->then(respond(200)->andBody('{"token": "abc123"}'))
        ->setScenario('auth')
);

// Transition state
$client->setScenarioState('auth', 'loggedIn');

// Verify subsequent requests
$client->createExpectation(
    on(getRequest('/api/profile'))
        ->then(respond(200)->andBody('{"user": "admin"}'))
        ->setScenario('auth')
        ->setScenarioState('profileLoaded')
);

3. Test Lifecycle Management

Reset state between tests:

public function tearDown(): void
{
    $this->phiremockClient->reset(); // Clears expectations, requests, and scenarios
}

4. Dynamic JSON Validation with JSON Path

Use JSON Path for flexible response validation:

$client->createExpectation(
    on(getRequest('/api/search'))
        ->then(
            respond(200)
                ->andBody(json_encode([
                    'results' => [
                        ['name' => 'Item 1'],
                        ['name' => 'Item 2']
                    ]
                ]))
        )
);

// Later, assert JSON Path in tests:
$response = Http::get('/api/search');
$this->assertEquals('Item 1', $response->jsonPath('$.results[0].name'));

5. Integration with Laravel HTTP Tests

Combine with Laravel’s HTTP testing:

public function test_user_creation()
{
    $this->phiremockClient->createExpectation(
        on(postRequest('/api/users'))
            ->then(respond(201)->andBody('{"id": 1}'))
    );

    $response = $this->postJson('/api/users', ['name' => 'John']);
    $response->assertStatus(201);
}

6. Custom HTTP Client Integration

Override the factory for non-Guzzle clients (e.g., Symfony HTTP Client):

use Symfony\Contracts\HttpClient\HttpClientInterface;

class SymfonyFactory extends Factory
{
    public function createRemoteConnection(): HttpClientInterface
    {
        return \Symfony\Contracts\HttpClient\HttpClient::create();
    }
}

// Usage:
$client = (new SymfonyFactory())
    ->createPhiremockClient(new Host('localhost'), new Port('8080'));

Gotchas and Tips

Pitfalls

  1. PHP Version Mismatch:

    • Issue: v2.0.0+ requires PHP 8.2+. Using older versions throws RuntimeException.
    • Fix: Downgrade to ^1.2 if stuck on PHP 8.1 or lower.
    • Tip: Check composer.json for platform-check or use php -v in CI.
  2. Guzzle Version Conflicts:

    • Issue: Guzzle v7+ may cause ClassNotFoundException if not configured.
    • Fix: Extend the factory (as shown in README) or pin Guzzle v6:
      "guzzlehttp/guzzle": "6.5"
      
  3. Scenario State Leaks:

    • Issue: Scenarios retain state between tests if not reset.
    • Fix: Call $client->resetScenarios() in tearDown() or use reset() for full cleanup.
  4. JSON Path Quirks:

    • Issue: JSON Path queries may fail on malformed JSON or missing keys.
    • Fix: Validate responses with json_decode() first:
      $data = json_decode($response->body(), true);
      $this->assertEquals('value', $data['key']);
      
  5. Port/Host Binding:

    • Issue: Phiremock Server must be running on the specified host/port.
    • Fix: Start the server in tests:
      $this->artisan('phiremock:serve', ['--port' => 8080]);
      

Debugging Tips

  1. List All Expectations:

    $expectations = $this->phiremockClient->listExpectations();
    dd($expectations); // Inspect in tests
    
  2. Inspect Executed Requests:

    $executions = $this->phiremockClient->listExecutions();
    dd($executions); // Debug mismatched requests
    
  3. Enable Phiremock Server Logging: Add to phiremock-server config:

    logging:
        level: DEBUG
    
  4. Validate JSON Path Queries: Use a tool like JSONPath Online Evaluator to test queries before coding.

Extension Points

  1. Custom Matchers: Extend Mcustiel\Phiremock\Client\Utils\Is to add domain-specific validators:

    class CustomIs extends Is
    {
        public static function isValidToken(): Is
        {
            return new self(function ($value) {
                return preg_match('/^Bearer [a-z0-9]{32}$/', $value);
            });
        }
    }
    
  2. Scenario State Transitions: Create a service to manage complex scenario logic:

    class AuthScenario
    {
        public function __construct(private PhiremockClient $client)
        {
        }
    
        public function login(string $token): void
        {
            $this->client->setScenarioState('auth', 'loggedIn');
            // Additional logic...
        }
    }
    
  3. Dynamic Expectation Generation: Use Laravel’s collect() to generate expectations from test data:

    $testCases = collect([
        ['url' => '/api/users', 'status' => 200, 'body' => '{}'],
        ['url' => '/api/posts', 'status' => 200, 'body' => '[]'],
    ]);
    
    $testCases->each(function ($case) {
        $this->phiremockClient->createExpectation(
            on(getRequest($case['url']))
                ->then(respond($case['status'])->andBody($case['body']))
        );
    });
    

Performance Considerations

  • Batch Operations: Clear/reset expectations in bulk where possible:
    $this->phiremockClient->reset(); // Faster than clearing individually
    
  • Avoid Over-Mocking: Limit expectations to critical paths to reduce server load.
  • Reuse Clients: Instantiate the client once per test suite (not per test) to avoid connection overhead.

Laravel-Specific Tips

  1. Service Provider Binding: Bind the client in AppServiceProvider for global access:

    public function register()
    {
        $this->app->singleton(PhiremockClient::class, function ($app) {
            return Factory::createDefault()
                ->createPhiremockClient(
                    new Host(config('phiremock.host')),
                    new Port(config('phiremock.port'))
                );
        });
    }
    
  2. Config Integration: Add to config/phiremock.php:

    return [
        'host' => env('PHIREMOCK_HOST', 'localhost'),
        'port' => env('PHIREMOCK_PORT', 8080),
        'scheme' => env('PHIREMOCK_SCHEME', 'http'),
    ];
    
  3. Test Helpers: Create a trait for reusable test logic:

    trait PhiremockTests
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor