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

orchestra/testbench

Orchestra Testbench is the de-facto Laravel testing helper for package development. It boots a lightweight Laravel app for your package’s tests, making it easy to run PHPUnit/Pest suites with proper service providers, config, and environment setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev orchestra/testbench
    

    Add to composer.json under require-dev:

    "orchestra/testbench": "^11.0"
    
  2. Basic Test Structure: Create a test class extending Orchestra\Testbench\TestCase (or Orchestra\Testbench\PHPUnit\TestCase for PHPUnit):

    use Orchestra\Testbench\TestCase;
    
    class ExampleTest extends TestCase
    {
        public function test_basic()
        {
            $this->assertTrue(true);
        }
    }
    
  3. First Use Case: Test a package service provider:

    public function test_service_provider()
    {
        $this->withWorkbench(function (Workbench $workbench) {
            $workbench->loadPackages([__DIR__.'/../vendor/package-name']);
            $this->assertTrue(app()->has('package-service'));
        });
    }
    

Key Starting Points

  • Official Docs: packages.tools/testbench
  • Skeleton Generator: Use orchestra/testbench-core for custom test skeletons.
  • Configuration: testbench.yaml for global test settings (e.g., seeders, database).

Implementation Patterns

Core Workflows

1. Package Integration Testing

  • Load Packages:
    $this->withWorkbench(function (Workbench $workbench) {
        $workbench->loadPackages([__DIR__.'/../vendor/package-name']);
        // Test logic here
    });
    
  • Disable Default Providers (if needed):
    $workbench->disableDefaultServiceProviders();
    

2. Database Testing

  • Migrations & Seeders: Configure testbench.yaml:
    seeders: true
    migrations: true
    
    Or manually:
    $this->withWorkbench(function (Workbench $workbench) {
        $workbench->loadMigrationsFrom([__DIR__.'/../database/migrations']);
        $workbench->runMigrations();
        $workbench->runSeeders();
    });
    
  • Fixtures: Use WithFixtures trait:
    use Orchestra\Testbench\Concerns\WithFixtures;
    
    class FixtureTest extends TestCase
    {
        use WithFixtures;
    
        protected function getFixturesPath()
        {
            return __DIR__.'/fixtures';
        }
    }
    

3. Mocking & Stubbing

  • Mockery Integration:
    $mock = Mockery::mock('alias:YourService');
    $mock->shouldReceive('method')->once();
    $this->app->instance('YourService', $mock);
    
  • Partial Mocks:
    $mock = Mockery::mock('partial', 'YourClass');
    $mock->shouldReceive('methodToMock')->andReturn('stubbed');
    

4. HTTP Testing

  • Route Testing:
    $response = $this->get('/test-route');
    $response->assertStatus(200);
    
  • Form Requests:
    $this->post('/submit', ['field' => 'value'])
         ->assertRedirect('/success');
    

5. Custom Skeleton

  • Extend Orchestra\Testbench\Workbench:
    class CustomWorkbench extends Workbench
    {
        protected function configure()
        {
            $this->mergeConfigFrom(__DIR__.'/config/custom.php', 'testbench');
        }
    }
    
  • Use in tests:
    $this->withWorkbench(CustomWorkbench::class, function (CustomWorkbench $workbench) {
        // ...
    });
    

Integration Tips

Artisan Commands

Test commands with:

$exitCode = Artisan::call('command:name', ['option' => 'value']);
$this->assertEquals(0, $exitCode);

Events & Listeners

Publish and listen to events:

Event::fake();
$listener = new YourListener();
Event::assertListeningTo(YourEvent::class, $listener);

Remote Commands

Execute remote commands (e.g., queue workers):

$output = Orchestra\Testbench\remote(function () {
    return shell_exec('php artisan queue:work --once');
});

Parallel Testing

Ensure WithFixtures is compatible with --parallel flag in PHPUnit:

# testbench.yaml
parallel: true

Gotchas and Tips

Common Pitfalls

1. State Persistence Between Tests

  • Issue: Eloquent models, Str::macro(), or other static states may persist.
  • Fix: Use flushState() or extend TestCase:
    use Orchestra\Testbench\Concerns\FlushesStates;
    
    class MyTest extends TestCase
    {
        use FlushesStates;
    }
    
  • Manual Flush:
    $this->flushStates();
    

2. Database Rollbacks

  • Issue: Migrations may not roll back cleanly in parallel tests.
  • Fix: Use SQLite in-memory DB for tests:
    $this->withWorkbench(function (Workbench $workbench) {
        $workbench->useDatabase('sqlite');
        $workbench->setUpDatabase($this);
    });
    

3. Service Provider Binding Conflicts

  • Issue: BindingResolutionException if providers bind the same service.
  • Fix: Use #[UsesVendor] attribute or manually resolve:
    $this->app->bind('conflicting-service', function () {
        return new YourService();
    });
    

4. Fixture Loading Order

  • Issue: Fixtures may depend on migrations not yet run.
  • Fix: Load migrations first:
    $this->withWorkbench(function (Workbench $workbench) {
        $workbench->loadMigrationsFrom([...]);
        $workbench->runMigrations();
        $this->loadFixtures();
    });
    

5. PHPUnit 13+ Compatibility

  • Issue: Deprecated annotations (@define-env, @define-db) no longer work.
  • Fix: Use testbench.yaml or setUp():
    protected function setUp(): void
    {
        parent::setUp();
        putenv('DB_CONNECTION=sqlite');
    }
    

Debugging Tips

Enable Verbose Logging

phpunit --verbose

Or in phpunit.xml:

<php>
    <env name="TESTBENCH_DEBUG" value="1"/>
</php>

Inspect Workbench State

$this->withWorkbench(function (Workbench $workbench) {
    dump($workbench->getLoadedPackages());
    dump($workbench->getConfiguredProviders());
});

Reset Testbench State

Orchestra\Testbench\flushStates();

Extension Points

Custom Assertions

Extend TestCase:

class CustomAssertionsTest extends TestCase
{
    protected function assertPackageVersion($package, $expected)
    {
        $actual = Orchestra\Testbench\package_version($package);
        $this->assertEquals($expected, $actual);
    }
}

Predefined Test Data

Use WithFixtures with JSON/YAML fixtures:

# fixtures/users.yml
users:
  - id: 1
    name: Test User

Parallel Test Isolation

Configure testbench.yaml:

parallel:
    enabled: true
    isolation: true

Custom Testbench Core

Override core behavior by extending Orchestra\Testbench\Workbench:

class CustomWorkbench extends Workbench
{
    public function customMethod()
    {
        // ...
    }
}

Configuration Quirks

testbench.yaml Overrides

  • Database: Override connection in database section:
    database:
        connection: sqlite
        migrations: database/migrations
    
  • Seeders: Enable with:
    seeders: true
    
  • Providers: Disable default providers:
    providers:
        disable: [App\Providers\AppServiceProvider]
    

Environment Variables

  • Use .env.testbench for test-specific configs.
  • Override in setUp():
    putenv('APP_ENV=testing');
    

PHPUnit Bootstrapping

  • Ensure bootstrap.php loads Testbench:
    require __DIR__.'/vendor/autoload.php';
    $
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony