Weave 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

Http Tester Laravel Package

draw/http-tester

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require --dev draw/http-tester
    
  2. Basic Test Setup Use the Tester trait in your PHPUnit test class:

    use Draw\HttpTester\Tester;
    
    class ApiTest extends TestCase
    {
        use Tester;
    }
    
  3. First Test Case Test a simple GET request with assertions:

    public function test_api_returns_expected_data()
    {
        $this->get('/api/users')
            ->assertStatus(200)
            ->assertJsonStructure(['data' => ['*' => ['id', 'name']]]);
    }
    
  4. Key Methods to Explore First

    • $this->get(), $this->post(), etc. for HTTP methods.
    • assertStatus(), assertBodyContains(), assertJson() for assertions.
    • withHeaders(), withQueryParams() for request modifications.

Implementation Patterns

Core Workflows

1. API Contract Testing

Validate responses against expected schemas:

public function test_user_endpoint_contract()
{
    $this->get('/api/users/1')
        ->assertStatus(200)
        ->assertJsonStructure([
            'id', 'name', 'email',
            'created_at', 'updated_at'
        ]);
}

2. Mocking Third-Party APIs

Simulate external API responses without network calls:

public function test_payment_gateway_integration()
{
    $this->post('/api/payments', ['amount' => 100])
        ->assertStatus(200)
        ->assertJsonPath('$.transaction_id', 'txn_12345');
}

3. Edge Case Testing

Test error scenarios deterministically:

public function test_authentication_failure()
{
    $this->withHeaders(['Authorization' => 'invalid'])
        ->get('/api/protected')
        ->assertStatus(401)
        ->assertJson(['error' => 'Unauthorized']);
}

4. Middleware Validation

Test route middleware behavior:

public function test_admin_middleware()
{
    $this->withHeaders(['X-Admin' => 'false'])
        ->get('/admin/dashboard')
        ->assertStatus(403);
}

Laravel Integration Patterns

1. Combining with Laravel's HTTP Testing

Use alongside Laravel's built-in testing tools:

public function test_laravel_integration()
{
    $response = $this->get('/api/users');
    $this->assertDatabaseCount('users', 3);
    $this->assertStatus($response, 200);
}

2. Service Provider Binding

Register HttpTester as a service for dependency injection:

// In a test service provider
$this->app->singleton(HttpTester::class, function () {
    return new HttpTester();
});

3. Custom Assertion Helpers

Create reusable assertion methods:

protected function assertApiSuccess($response)
{
    $this->assertStatus($response, 200);
    $this->assertJson($response);
    $this->assertJsonStructure($response, ['data', 'meta']);
}

4. Testing API Resources

Validate API resource transformations:

public function test_user_resource()
{
    $this->get('/api/users/1')
        ->assertStatus(200)
        ->assertJsonPath('$.data.name', 'John Doe');
}

Gotchas and Tips

Common Pitfalls

  1. PSR-7 Compatibility Issues

    • Problem: Some Laravel responses may not fully comply with PSR-7.
    • Solution: Use getResponse() to inspect raw PSR-7 objects:
      $response = $this->get('/')->getResponse();
      $this->assertInstanceOf(Psr\Http\Message\ResponseInterface::class, $response);
      
  2. Missing CSRF Token

    • Problem: POST/PUT requests to Laravel routes may fail without CSRF token.
    • Solution: Add CSRF token manually:
      $this->post('/form', [
          '_token' => csrf_token(),
          'data' => 'value'
      ]);
      
  3. Session Handling

    • Problem: Session-based authentication may not persist across tests.
    • Solution: Use withSession():
      $this->withSession(['user_id' => 1])
          ->get('/dashboard');
      
  4. Guzzle Under the Hood

    • Problem: Some Guzzle-specific behaviors (like redirects) may not work as expected.
    • Solution: Disable redirects if needed:
      $this->get('/redirect-endpoint', ['allow_redirects' => false]);
      
  5. Assertion Order Sensitivity

    • Problem: Chained assertions may fail if order matters.
    • Solution: Break into separate assertions:
      $response = $this->get('/');
      $this->assertStatus($response, 200);
      $this->assertBodyContains($response, 'Welcome');
      

Debugging Techniques

  1. Inspect Raw Response

    $response = $this->get('/')->getResponse();
    file_put_contents('debug_response.txt', $response->getBody());
    
  2. Enable Verbose Output

    $this->get('/')->setVerbose(true);
    
  3. Check Headers and Cookies

    $this->get('/')
        ->assertHeader('Content-Type', 'application/json')
        ->assertCookie('session', 'value');
    

Configuration Quirks

  1. Default Assertion Behavior

    • By default, assertions throw exceptions on failure. To return boolean:
      $this->assertStatus($response, 200, false);
      
  2. Custom Matchers

    • Register custom matchers for complex validation:
      $this->get('/')
          ->assertCustom(function ($response) {
              $body = json_decode($response->getBody(), true);
              $this->assertArrayHasKey('expected_key', $body);
          });
      
  3. Performance Considerations

    • For large test suites, disable verbose output:
      $this->setVerbose(false);
      

Extension Points

  1. Custom HTTP Client

    • Replace the default client:
      $this->setClient(new GuzzleHttp\Client(['base_uri' => 'http://test.local']));
      
  2. Middleware Hooks

    • Add middleware to test requests:
      $this->addMiddleware(function ($request) {
          $request = $request->withHeader('X-Custom', 'Header');
          return $request;
      });
      
  3. Response Transformers

    • Modify responses before assertions:
      $this->get('/')
          ->transformResponse(function ($response) {
              return $response->withHeader('X-Processed', 'true');
          })
          ->assertHeader('X-Processed', 'true');
      
  4. Integration with Laravel Events

    • Listen to test events:
      $this->on('beforeRequest', function ($request) {
          // Modify request before sending
      });
      
  5. Custom Assertion Classes

    • Extend the base assertion class:
      class CustomAssertions extends Assertions
      {
          public function assertCustomValidation($response, $rules)
          {
              // Custom validation logic
          }
      }
      
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log