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

graham-campbell/testbench-core

Core testing utilities for Laravel packages, maintained by Graham Campbell. Provides lightweight TestBench components compatible with Laravel 8–13, PHP 7.4–8.5, and PHPUnit 9–12 to simplify package test setup and integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev graham-campbell/testbench-core:^4.3
    
    • No configuration required. Works out-of-the-box with Laravel 8–13 and PHPUnit 9–12.
  2. First Use Case: Extend a test class with the provided traits (e.g., MockeryTrait, ServiceProviderTrait) to leverage Laravel-specific testing utilities.

    use GrahamCampbell\TestbenchCore\Traits\MockeryTrait;
    
    class ExampleTest extends TestCase
    {
        use MockeryTrait;
    
        public function testMockingExample()
        {
            $mock = $this->mock('App\Services\ExampleService');
            $mock->shouldReceive('process')->once()->andReturn('mocked');
    
            $result = app('App\Services\ExampleService')->process();
            $this->assertEquals('mocked', $result);
        }
    }
    
  3. Key Entry Points:

    • Traits: MockeryTrait, ServiceProviderTrait, FacadeTrait, DatabaseTrait (for database testing).
    • Assertions: Extended PHPUnit assertions like assertArraySubset or Laravel-specific helpers.
    • Documentation: Check Graham Campbell’s other packages for usage examples (e.g., Laravel-TestBench).

Implementation Patterns

Core Workflows

  1. Mocking Laravel Components:

    • Use MockeryTrait to mock services, repositories, or facades without manual setup.
      $this->mock('App\Contracts\PaymentGateway')
           ->shouldReceive('charge')
           ->with(100)
           ->andThrow(new \Exception('Test failure'));
      
    • Pattern: Prefer mocking contracts/interfaces over concrete classes for better test isolation.
  2. Service Provider Testing:

    • Extend ServiceProviderTrait to test bindings, macros, or service provider logic.
      use GrahamCampbell\TestbenchCore\Traits\ServiceProviderTrait;
      
      class PaymentServiceProviderTest extends TestCase
      {
          use ServiceProviderTrait;
      
          public function testBindings()
          {
              $this->assertServiceProviderClass('App\Providers\PaymentServiceProvider');
              $this->assertBound('payment.gateway');
          }
      }
      
    • Pattern: Use assertServiceProviderClass() to verify the correct provider is registered.
  3. Facade Testing:

    • Leverage FacadeTrait to test facades by mocking their underlying classes.
      use GrahamCampbell\TestbenchCore\Traits\FacadeTrait;
      
      class NotificationFacadeTest extends TestCase
      {
          use FacadeTrait;
      
          public function testFacadeMocking()
          {
              $this->mockFacade('Notification', 'App\Services\NotificationService');
              $this->assertEquals('mocked', Notification::send());
          }
      }
      
    • Pattern: Combine with MockeryTrait for granular control over facade methods.
  4. Database Testing:

    • Use DatabaseTrait (if available in future versions) or manually set up migrations/seeds in tests.
      $this->artisan('migrate:fresh');
      $this->artisan('db:seed', ['--class' => 'UserSeeder']);
      

Integration Tips

  • Combine with Laravel TestCase: Always extend Laravel’s TestCase (or RefreshDatabase/CreatesApplication) alongside TestBench traits.

    use Illuminate\Foundation\Testing\TestCase as LaravelTestCase;
    
    class UserTest extends LaravelTestCase
    {
        use MockeryTrait;
        // ...
    }
    
  • Custom Assertions: Extend the package’s assertions in your test classes:

    use GrahamCampbell\TestbenchCore\Traits\AssertionsTrait;
    
    class CustomAssertionsTest extends TestCase
    {
        use AssertionsTrait;
    
        public function testArraySubset()
        {
            $this->assertArraySubset(['key' => 'value'], ['key' => 'value', 'extra' => 'data']);
        }
    }
    
  • Test Doubles: Prefer partial mocks for facades/services to avoid over-mocking:

    $mock = $this->partialMock('App\Facades\Logger', ['log']);
    $mock->shouldReceive('log')->with('error')->once();
    
  • Performance: Reuse mocks across test methods where possible to reduce setup overhead:

    protected function setUp(): void
    {
        $this->mock = $this->mock('App\Services\CacheService');
        parent::setUp();
    }
    

Gotchas and Tips

Pitfalls

  1. Mockery Deprecation:

    • Issue: MockeryTrait may trigger deprecation warnings in PHPUnit 12+ (fixed in v4.2.1+).
    • Fix: Update to the latest version or suppress warnings if using an older version.
      $this->mock('Class')->shouldReceive('method')->andReturn('value');
      // Use `->ignoreDeprecations()` if needed (Mockery 1.4+).
      
  2. Static Method Changes (v4.0+):

    • Issue: Methods like getFacadeAccessor() became static in v4.0, breaking older code.
    • Fix: Update calls to use the static context:
      // Before v4.0:
      $this->getFacadeAccessor();
      // After v4.0:
      FacadeTrait::getFacadeAccessor();
      
  3. PHPUnit Version Mismatch:

    • Issue: PHPUnit 13 is unsupported due to "volatility across minor releases."
    • Fix: Pin to PHPUnit 12 in composer.json:
      "require-dev": {
          "phpunit/phpunit": "^12.0"
      }
      
  4. Service Provider Traits:

    • Issue: getServiceProviderClass() no longer accepts the app parameter (v4.0+).
    • Fix: Use the static method:
      $providerClass = ServiceProviderTrait::getServiceProviderClass('App\Providers\ExampleProvider');
      
  5. Database State:

    • Issue: Tests may fail if database state isn’t reset between runs.
    • Fix: Use RefreshDatabase trait or manually reset:
      public function tearDown(): void
      {
          Artisan::call('migrate:rollback');
          parent::tearDown();
      }
      

Debugging Tips

  • Mock Verification: Use Mockery’s shouldHaveReceived() to debug unexpected calls:

    $this->mock->shouldHaveReceived('method')->once();
    
  • Facade Root Inspection: Debug facade resolution with:

    dd(FacadeTrait::getFacadeRoot('Notification'));
    
  • Service Provider Binding: Check bindings with:

    $this->assertBound('contract.name');
    $this->assertInstanceOf('App\Services\Example', app('contract.name'));
    

Extension Points

  1. Custom Traits: Extend existing traits to add domain-specific testing logic:

    trait CustomTestTrait
    {
        protected function mockPaymentGateway()
        {
            return $this->mock('App\Contracts\PaymentGateway')
                ->shouldReceive('charge')
                ->andReturn(true);
        }
    }
    
  2. Assertion Helpers: Add custom assertions to the AssertionsTrait:

    use PHPUnit\Framework\Assert;
    
    trait CustomAssertions
    {
        protected function assertResponseHasStatus($expected, $response)
        {
            Assert::assertEquals($expected, $response->getStatusCode());
        }
    }
    
  3. Test Data Factories: Combine with Laravel’s factories for realistic test data:

    public function testUserCreation()
    {
        $user = User::factory()->create();
        $this->assertDatabaseHas('users', ['email' => $user->email]);
    }
    
  4. Parallel Testing: Use PHPUnit’s --parallel flag with TestBench for faster suites:

    phpunit --parallel
    

Pro Tips

  • Test Isolation: Use beforeApplicationDestroyed() to clean up mocks:

    protected function beforeApplicationDestroyed()
    {
        $this->mockery->close();
    }
    
  • Legacy Code: For Laravel <8, use v3.4 of TestBench Core for compatibility:

    composer require graham-campbell/testbench-core:^3.4 --dev
    
  • CI Optimization: Cache Composer dependencies and use --testdox-html for readable reports:

    composer install --prefer-dist --no-interaction
    phpunit --testdox-html report.html
    
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.
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
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata