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

Testbench Laravel Package

sampoyigi/testbench

Laravel testbench helpers for package development: quickly boot a minimal app, configure service providers, run migrations, and write reliable integration tests. Lightweight scaffolding to speed up local CI-style testing for your Laravel packages.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation Require the package via Composer in your Laravel project:

    composer require sampoyigi/testbench --dev
    

    Publish the configuration (if applicable) with:

    php artisan vendor:publish --provider="Sampoyigi\Testbench\TestbenchServiceProvider"
    
  2. First Use Case: Basic HTTP Test Write a simple HTTP test using Laravel’s native testing syntax, enhanced by Testbench:

    use Sampoyigi\Testbench\Facades\Testbench;
    use Tests\TestCase;
    
    class UserLoginTest extends TestCase
    {
        public function test_user_can_login()
        {
            Testbench::actingAsUser(); // Custom helper (if provided)
            $response = $this->post('/login', [
                'email' => 'test@example.com',
                'password' => 'password'
            ]);
            $response->assertStatus(200);
        }
    }
    
  3. Where to Look First

    • Facade Methods: Check Sampoyigi\Testbench\Facades\Testbench for utility methods like actingAsUser(), mockService(), or assertDatabaseState().
    • TestCase Traits: Review Sampoyigi\Testbench\Traits\* for reusable test behaviors (e.g., RefreshesDatabase, InteractsWithTime).
    • Artisan Commands: If the package includes test-related commands (e.g., testbench:run), inspect config/testbench.php for configuration options.

Implementation Patterns

Fluent Test Workflows

Use Testbench’s fluent interface to structure tests hierarchically, reducing boilerplate:

Testbench::test('User Profile')
    ->describe('GET /profile', function () {
        $this->get('/profile')
            ->assertStatus(200)
            ->assertJsonStructure(['id', 'name', 'email']);
    })
    ->describe('PUT /profile', function () {
        $this->put('/profile', ['name' => 'Updated Name'])
            ->assertStatus(200)
            ->assertJson(['name' => 'Updated Name']);
    });

Database Testing Patterns

Leverage Testbench’s database utilities for isolated tests:

Testbench::test('Order Creation')
    ->withDatabaseTransactions()
    ->it('creates an order', function () {
        $response = $this->post('/orders', ['product_id' => 1]);
        $response->assertCreated();
        $this->assertDatabaseHas('orders', ['product_id' => 1]);
    });

Mocking External Services

Simulate third-party services (e.g., payment gateways) without real API calls:

Testbench::test('Payment Processing')
    ->mock('Stripe', function ($mock) {
        $mock->shouldReceive('charge')
            ->once()
            ->andReturn(['status' => 'succeeded']);
    })
    ->it('processes a payment', function () {
        $this->post('/payments', ['amount' => 100])
            ->assertStatus(200);
    });

Artisan Command Testing

Test CLI commands with Testbench’s helpers:

Testbench::test('Artisan Commands')
    ->it('runs a custom command', function () {
        $this->artisan('testbench:generate:test', ['name' => 'UserTest'])
            ->expectsOutput('Test generated successfully.')
            ->assertExitCode(0);
    });

Integration with Laravel Events

Test event listeners or broadcasts:

Testbench::test('Event Broadcasting')
    ->listensTo('OrderPlaced')
    ->it('broadcasts the event', function () {
        event(new OrderPlaced());
        $this->assertBroadcasting('orders.placed');
    });

Gotchas and Tips

Common Pitfalls

  1. Facade Method Conflicts Avoid naming custom test methods test() or describe() to prevent collisions with Testbench’s fluent methods. Use descriptive names like runLoginTest() instead.

  2. Database State Leaks If using withDatabaseTransactions(), ensure no tests rely on shared state. Reset factories or seeders between tests:

    Testbench::test('Database Isolation')
        ->beforeEach(function () {
            User::factory()->create(['name' => 'Test User']);
        })
        ->it('does not leak data', function () {
            $this->assertDatabaseCount('users', 1);
        });
    
  3. Mocking Quirks Testbench’s mocking may override Laravel’s native mocking. Prefer explicit mocks:

    // Avoid:
    $this->mock('Stripe', ...);
    
    // Use instead:
    Testbench::mock('Stripe', ...);
    
  4. Configuration Overrides If the package publishes config, ensure your .env.testing overrides are applied:

    php artisan config:clear
    

    after publishing the config.

Debugging Tips

  • Test Output Logging Enable verbose output for failing tests:

    phpunit --verbose
    

    or use Testbench’s debug mode:

    Testbench::debug(true);
    
  • Isolated Test Environments For flaky tests, run tests in parallel with:

    phpunit --parallel
    

    and ensure Testbench’s isolation features (e.g., withFreshDatabase()) are used.

  • Dependency Conflicts If tests fail due to version mismatches, pin dependencies in composer.json:

    "require-dev": {
        "sampoyigi/testbench": "1.0.*",
        "laravel/testbench": "^10.0"
    }
    

Extension Points

  1. Custom Assertions Extend Testbench’s assertions by creating a trait:

    use Sampoyigi\Testbench\Traits\TestbenchAssertions;
    
    trait CustomAssertions {
        public function assertResponseHasError($response, $field) {
            $response->assertJsonStructure(['errors' => [$field]]);
        }
    }
    
    class UserTest extends TestCase {
        use TestbenchAssertions, CustomAssertions;
    }
    
  2. Test Helpers Add reusable test helpers to app/Helpers/TestbenchHelper.php:

    if (!function_exists('createTestUser')) {
        function createTestUser() {
            return User::factory()->create(['email' => 'test@example.com']);
        }
    }
    
  3. CI/CD Integration Configure GitHub Actions or GitLab CI to run tests with Testbench:

    # .github/workflows/tests.yml
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - run: composer install --dev
          - run: php artisan testbench:run
    

Performance Optimization

  • Skip Redundant Tests Use Testbench’s skipIf() to conditionally run tests:

    Testbench::test('Feature X')
        ->skipIf(app()->environment('production'))
        ->it('runs only in non-production', function () {
            // Test logic
        });
    
  • Parallel Test Execution Split tests by feature into separate files and run in parallel:

    phpunit --group=auth --parallel
    

Security Considerations

  • Sensitive Data in Tests Avoid hardcoding secrets. Use .env.testing:

    STRIPE_SECRET=test_sk_123
    

    and load it in phpunit.xml:

    <env name="APP_ENV" value="testing"/>
    
  • Test Data Sanitization Clear sensitive test data after execution:

    Testbench::test('Cleanup')
        ->afterEach(function () {
            DB::table('users')->where('email', 'test@example.com')->delete();
        });
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
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