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 Core Laravel Package

orchestra/testbench-core

Testbench Core is the foundation for Orchestra Testbench, providing a lightweight Laravel application bootstrap for package testing. Run artisan commands, migrations, factories, and routes in your test suite with versioned Laravel compatibility.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev orchestra/testbench-core
    

    Ensure version compatibility with your Laravel version (e.g., Laravel 12.x → Testbench Core 10.x).

  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's service provider registration:

    public function test_service_provider_registration()
    {
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
        $this->assertTrue($this->app->has('MyServiceProvider'));
    }
    

Key Starting Points

  • setUp(): Override to configure the test environment (e.g., load migrations, bind services).
  • getPackageProviders(): Define package providers for testing:
    protected function getPackageProviders($app)
    {
        return ['MyPackage\\Providers\\MyServiceProvider'];
    }
    
  • getEnvironmentSetUp(): Configure environment (e.g., database, queues):
    protected function getEnvironmentSetUp($app)
    {
        $app['config']->set('database.default', 'sqlite_memory');
    }
    

Implementation Patterns

Core Workflows

  1. Testing Service Providers:

    public function test_provider_boot()
    {
        $this->assertTrue($this->app->bound('my.bound.service'));
    }
    
  2. Testing Artisan Commands: Use Artisan::call() or Artisan::assertExitCode():

    public function test_custom_command()
    {
        Artisan::call('my:command', ['option' => 'value']);
        $this->assertStringContainsString('Success', Artisan::output());
    }
    
  3. Testing Migrations: Load migrations in setUp() and assert schema:

    public function test_migration()
    {
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
        $this->assertDatabaseHas('table_name', ['column' => 'value']);
    }
    
  4. Testing Routes: Use get() or post() with TestResponse:

    public function test_route()
    {
        $response = $this->get('/api/endpoint');
        $response->assertStatus(200);
    }
    
  5. Testing Middleware: Override getMiddlewareGroups() or getMiddleware():

    protected function getMiddlewareGroups($middlewareGroups)
    {
        return array_merge(parent::getMiddlewareGroups($middlewareGroups), [
            'web' => ['App\Http\Middleware\MyMiddleware'],
        ]);
    }
    

Integration Tips

  • Mocking Dependencies: Use Mockery (included via InteractsWithMockery trait):

    $mock = Mockery::mock('App\Contracts\MyContract');
    $this->app->instance('App\Contracts\MyContract', $mock);
    
  • Testing Events: Use Events::assertDispatched():

    Events::assertDispatched(MyEvent::class);
    
  • Testing Jobs/Queues: Use Queue::fake() and Queue::assertPushed():

    Queue::fake();
    MyJob::dispatch();
    Queue::assertPushed(MyJob::class);
    
  • Testing API Resources: Use JsonResource assertions:

    $response = $this->getJson('/api/resource');
    $response->assertJsonStructure(['data' => ['id', 'name']]);
    
  • Parallel Testing: Configure testbench.yaml for parallel runs:

    seeders: true
    

Advanced Patterns

  • Custom Skeleton: Extend Orchestra\Testbench\Skeleton\Skeleton to override default Laravel setup.

  • Remote Testing: Use Orchestra\Testbench\remote() for cross-package testing:

    $result = remote(function () {
        return app()->version();
    });
    
  • Fixtures: Use WithFixtures trait to load test data:

    use Orchestra\Testbench\Concerns\WithFixtures;
    
    public function test_with_fixtures()
    {
        $this->loadFixtures(['users']);
        $this->assertDatabaseHas('users', ['email' => 'test@example.com']);
    }
    

Gotchas and Tips

Common Pitfalls

  1. Database Rollbacks:

    • Issue: Tests may fail if migrations aren’t rolled back between tests.
    • Fix: Use refreshDatabase() or refreshMigrations() in setUp():
      public function setUp(): void
      {
          parent::setUp();
          $this->refreshDatabase();
      }
      
  2. Service Provider Loading:

    • Issue: Providers may not load if not listed in getPackageProviders().
    • Fix: Ensure all required providers are included:
      protected function getPackageProviders($app)
      {
          return ['Vendor\\Package\\Providers\\ServiceProvider'];
      }
      
  3. Environment Configuration:

    • Issue: Tests may use incorrect .env settings.
    • Fix: Override in getEnvironmentSetUp():
      $app['config']->set('app.debug', false);
      
  4. Mockery vs. PHPUnit:

    • Issue: Conflicts between Mockery and PHPUnit mocks.
    • Fix: Use Mockery::close() in tearDown():
      public function tearDown(): void
      {
          Mockery::close();
          parent::tearDown();
      }
      
  5. Parallel Testing:

    • Issue: Fixtures or migrations may conflict in parallel runs.
    • Fix: Configure testbench.yaml:
      seeders: false  # Disable if using custom fixtures
      
  6. Artisan Command Output:

    • Issue: Artisan::call() may not capture output correctly.
    • Fix: Use Artisan::output() or expectsOutput():
      Artisan::call('command', ['--option' => 'value']);
      $this->assertStringContainsString('Expected', Artisan::output());
      

Debugging Tips

  • Enable Debug Mode: Set APP_DEBUG=true in getEnvironmentSetUp() for verbose errors.

  • Log Test Output: Use dd() or dump() sparingly; prefer assert methods.

  • Isolate Tests: Avoid shared state between tests (e.g., static variables, global configs).

  • Check for Deprecations: Use Orchestra\Testbench\terminate() or bail() to exit tests early if needed.

Configuration Quirks

  1. testbench.yaml:

    • seeders: true: Runs database seeders before tests.
    • parallel: true: Enables parallel test execution (requires PHPUnit 9+).
  2. Custom Skeleton:

    • Override Orchestra\Testbench\Skeleton\Skeleton to modify Laravel’s default setup.
    • Example: Disable default providers:
      protected function configureSkeleton(Skeleton $skeleton)
      {
          $skeleton->withoutDefaultProviders();
      }
      
  3. Terminating Console:

    • Testbench overrides ServeCommand to use TerminatingConsole for better test isolation.

Extension Points

  1. Custom Assertions: Extend Orchestra\Testbench\TestCase to add domain-specific assertions.

  2. Test Traits: Create reusable traits for common test logic (e.g., WithCustomFixtures).

  3. Remote Testing: Use Orchestra\Testbench\remote() to test packages in isolation.

  4. PestPHP Support: Testbench Core supports PestPHP via testbench.yaml configuration:

    pest: true
    
  5. Flushing States: Manually flush Laravel states (e.g., Str, Validator) in tearDown():

    public function tearDown(): void
    {
        \Illuminate\Support\Str::flushStates();
        parent::tearDown();
    }
    

Pro Tips

  • Use WithFixtures for complex test data setup.
  • Leverage package_version_compare() to test version-specific behavior.
  • Disable Default Providers if your package replaces core functionality:
    $skeleton->withoutDefaultProviders();
    
  • Test Edge Cases: Use Orchestra\Testbench\bail() to handle unrecoverable failures in parallel tests.
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport