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

graham-campbell/testbench

Testing utilities for Laravel packages, built on PHPUnit, Mockery, Orchestral Testbench, and Laravel Testbench Core. Supports Laravel 8–13 and PHP 7.4–8.5, with compatibility for PHPUnit 9–11 to help you run fast, reliable package test suites.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev graham-campbell/testbench:^6.3
    

    No additional configuration is required.

  2. First Test Case: Extend GrahamCampbell\TestBench\AbstractTestCase in your test file:

    use GrahamCampbell\TestBench\AbstractTestCase;
    
    class ExampleTest extends AbstractTestCase
    {
        public function testBasicSetup()
        {
            $this->assertTrue(true);
        }
    }
    
  3. Run Tests:

    phpunit
    

First Use Case: Package Testing

For testing a Laravel package, extend GrahamCampbell\TestBench\AbstractPackageTestCase:

use GrahamCampbell\TestBench\AbstractPackageTestCase;

class PackageTest extends AbstractPackageTestCase
{
    protected function getPackageProviders($app)
    {
        return ['YourPackage\\ServiceProvider'];
    }

    public function testPackageBootstrap()
    {
        $this->assertTrue(true);
    }
}

Implementation Patterns

Core Workflows

1. Application Testing

  • Extend AbstractAppTestCase for full Laravel app testing.
  • Override getBasePath() to specify your app’s root directory:
    protected static function getBasePath()
    {
        return __DIR__ . '/../../';
    }
    

2. Package Testing

  • Extend AbstractPackageTestCase for isolated package testing.
  • Define required service providers in getRequiredServiceProviders() (static method):
    protected static function getRequiredServiceProviders()
    {
        return ['YourPackage\\ServiceProvider'];
    }
    
  • Use getPackage() to access your package instance:
    $package = $this->getPackage();
    

3. Mocking and Assertions

  • Leverage Mockery for mocking dependencies:
    $mock = $this->mock('Your\\Contract');
    $mock->shouldReceive('method')->once();
    
  • Use built-in assertions like assertInJson() for HTTP responses:
    $response = $this->call('GET', '/api/endpoint');
    $this->assertInJson($response, ['key' => 'value']);
    

4. Database Testing

  • Use createApplication() with a database configuration:
    $app = $this->createApplication();
    $app->make('db')->connection()->getSchemaBuilder()->create('table_name', function ($table) {
        $table->increments('id');
    });
    

5. Service Container Binding

  • Bind interfaces to mocks in setUp():
    $this->app->bind('Your\\Interface', function () {
        return $this->mock('Your\\Interface');
    });
    

Integration Tips

Testing HTTP Routes

Use call() for HTTP requests:

$response = $this->call('GET', '/route', ['param' => 'value']);
$this->assertEquals(200, $response->getStatusCode());

Testing Middleware

Override getMiddleware() in AbstractPackageTestCase:

protected function getMiddleware()
{
    return ['YourPackage\\Middleware'];
}

Testing Events

Use expectsEvents() to verify event dispatching:

Event::expectsEvents('Your\\Event');

Testing Jobs/Queues

Mock the queue connection:

$this->app->bind('queue', function () {
    return $this->mock('Illuminate\\Contracts\\Queue\\Queue');
});

Testing Artisan Commands

Use artisan() helper:

$this->artisan('command:name', ['option' => 'value'])
     ->assertExitCode(0);

Gotchas and Tips

Pitfalls

  1. Static Methods in V6+:

    • getBasePath() and getRequiredServiceProviders() are now static in AbstractAppTestCase and AbstractPackageTestCase, respectively. Avoid passing $app as a parameter.
    • Fix: Update overrides to match the static signature:
      protected static function getBasePath() { ... }
      protected static function getRequiredServiceProviders() { ... }
      
  2. PHPUnit Version Conflicts:

    • TestBench supports PHPUnit 9-11 (excluding 12 due to volatility). Ensure your phpunit.xml aligns:
      <phpunit bootstrap="vendor/autoload.php">
          <php>
              <ini name="error_reporting" value="-1" />
          </php>
      </phpunit>
      
    • Gotcha: PHPUnit 12 is explicitly unsupported. Use ^11.0 or ^9.0 in composer.json.
  3. Mockery Assertions:

    • Mockery assertions (e.g., shouldReceive()) must be called before the method under test. Reorder logic if assertions fail unexpectedly.
  4. Database Transactions:

    • Tests run in transactions by default. Explicitly roll back or commit if needed:
      $this->beginDatabaseTransaction();
      // Test logic
      $this->rollBackDatabaseTransaction();
      
  5. Service Provider Loading:

    • If providers fail to load, verify:
      • The namespace in getRequiredServiceProviders() is correct.
      • The provider’s register() method doesn’t assume a loaded app (e.g., no app['config'] calls before boot()).

Debugging Tips

  1. Enable Debug Mode: Set APP_DEBUG=true in .env.testing or override in setUp():

    $this->app->bind('app.debug', function () {
        return true;
    });
    
  2. Dump the App: Inspect the Laravel container in tests:

    dump($this->app->make('config')->get('app.key'));
    
  3. Isolate Tests: Use refreshApplication() to reset the app between tests:

    public function tearDown(): void
    {
        $this->refreshApplication();
        parent::tearDown();
    }
    
  4. Check for Conflicts: Run composer why-not graham-campbell/testbench to detect version conflicts.


Extension Points

  1. Custom Test Cases: Extend AbstractTestCase to add reusable test logic:

    abstract class CustomTestCase extends AbstractTestCase
    {
        protected function mockHttpClient()
        {
            return $this->mock('GuzzleHttp\\Client');
        }
    }
    
  2. Override Fixtures: Customize the test environment by overriding createApplication():

    protected function createApplication()
    {
        $app = parent::createApplication();
        $app['config']->set('app.timezone', 'UTC');
        return $app;
    }
    
  3. Add Assertions: Use PHPUnit’s @method annotation to add custom assertions to your test case:

    /**
     * @method void assertInJson(array $response, array $expected)
     */
    class CustomAssertionsTest extends AbstractTestCase { ... }
    
  4. Integration with Pest: TestBench works with Pest via pest.php:

    uses(GrahamCampbell\TestBench\AbstractTestCase::class)->in('Tests');
    

Configuration Quirks

  1. Environment Files: TestBench uses .env.testing by default. Copy .env to .env.testing and customize:

    APP_ENV=testing
    DB_CONNECTION=sqlite_memory
    
  2. Encryption Key: TestBench sets a dummy key automatically. For encrypted data tests, override:

    $this->app['config']->set('app.key', 'base64:your-key-here');
    
  3. Queue Workers: Disable queues in tests to avoid background processes:

    $this->app['queue.worker'] = $this->mock('Illuminate\\Queue\\Worker');
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope