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 or service provider registration is required.

  2. First Use Case: Extend a test class with the provided traits (e.g., FacadeTrait, MockeryTrait, ServiceProviderTrait) to leverage Laravel-specific testing utilities. Example:

    use GrahamCampbell\TestbenchCore\Traits\MockeryTrait;
    
    class ExampleTest extends TestCase
    {
        use MockeryTrait;
    
        public function testMocking()
        {
            $mock = $this->mock('App\Services\PaymentService');
            $mock->shouldReceive('charge')->once();
            // Test logic here
        }
    }
    
  3. Key Entry Points:

    • Traits: FacadeTrait, MockeryTrait, ServiceProviderTrait (see Usage for details).
    • Assertions: Extended PHPUnit assertions like assertArraySubset or assertInternalType.
    • Documentation: Review the changelog for version-specific features (e.g., PHP 8.5 or Laravel 13 support).

Implementation Patterns

Core Workflows

1. Mocking Laravel Components

  • Use MockeryTrait to mock services, repositories, or facades without manual setup.
  • Pattern:
    use GrahamCampbell\TestbenchCore\Traits\MockeryTrait;
    
    class UserServiceTest extends TestCase
    {
        use MockeryTrait;
    
        public function testUserCreation()
        {
            $mockRepository = $this->mock('App\Repositories\UserRepository');
            $mockRepository->shouldReceive('create')
                ->once()
                ->andReturn(['id' => 1, 'name' => 'Test User']);
    
            $service = new UserService($mockRepository);
            $result = $service->createUser(['name' => 'Test User']);
    
            $this->assertEquals(['id' => 1, 'name' => 'Test User'], $result);
        }
    }
    
  • Tip: Combine with Laravel’s partialMock() for partial mocking of bound services.

2. Testing Facades

  • Use FacadeTrait to test facade interactions without instantiating underlying classes.
  • Pattern:
    use GrahamCampbell\TestbenchCore\Traits\FacadeTrait;
    
    class NotificationTest extends TestCase
    {
        use FacadeTrait;
    
        protected function getFacadeAccessor()
        {
            return 'notifications';
        }
    
        public function testSendNotification()
        {
            $this->partialMock('App\Facades\Notification', function ($mock) {
                $mock->shouldReceive('send')
                    ->once()
                    ->with('email', 'user@example.com');
            });
    
            Notification::send('email', 'user@example.com');
        }
    }
    
  • Tip: Override getFacadeAccessor() to specify the binding key for your facade.

3. Service Provider Testing

  • Use ServiceProviderTrait to test service provider registrations and bindings.
  • Pattern:
    use GrahamCampbell\TestbenchCore\Traits\ServiceProviderTrait;
    
    class AuthServiceProviderTest extends TestCase
    {
        use ServiceProviderTrait;
    
        protected function getServiceProviderClass()
        {
            return 'App\Providers\AuthServiceProvider';
        }
    
        public function testRegisterBindings()
        {
            $this->assertServiceBound('auth');
            $this->assertInstanceOf(
                AuthManager::class,
                app('auth')
            );
        }
    }
    
  • Tip: Use assertServiceBound() to verify bindings exist before testing.

4. Custom Assertions

  • Extend PHPUnit assertions with Laravel-specific helpers.
  • Examples:
    $this->assertArraySubset(['id' => 1], $userData); // Check if subset exists
    $this->assertInternalType('array', $response->data); // Strict type checking
    

Integration Tips

With Laravel Packages

  • For packages, use ServiceProviderTrait to test provider registrations in isolation:
    class PackageServiceProviderTest extends TestCase
    {
        use ServiceProviderTrait;
    
        protected function getServiceProviderClass()
        {
            return 'Vendor\Package\PackageServiceProvider';
        }
    
        public function testPackageBindings()
        {
            $this->assertServiceBound('package.config');
        }
    }
    

With API Testing

  • Combine with MockeryTrait to mock external services (e.g., payment gateways):
    public function testPaymentProcessing()
    {
        $mockGateway = $this->mock('App\Services\PaymentGateway');
        $mockGateway->shouldReceive('charge')
            ->once()
            ->andReturn(true);
    
        $response = $this->post('/pay', ['amount' => 100]);
        $this->assertEquals(200, $response->status());
    }
    

With Database Testing

  • Use MockeryTrait to mock Eloquent models or repositories:
    public function testUserModel()
    {
        $mockUser = $this->mock('App\Models\User');
        $mockUser->shouldReceive('find')
            ->once()
            ->andReturn(new User());
    
        $user = User::find(1);
        $this->assertInstanceOf(User::class, $user);
    }
    

Gotchas and Tips

Pitfalls

  1. Static Method Changes (v4.0+)

    • Methods like getFacadeAccessor() in FacadeTrait are now static. Update overrides:
      // Old (pre-v4.0):
      protected function getFacadeAccessor() { ... }
      
      // New (v4.0+):
      protected static function getFacadeAccessor() { ... }
      
  2. Mockery Deprecation Warnings

    • In MockeryTrait, ensure you’re using shouldReceive() (not shouldReceive('method') without parentheses) to avoid deprecation warnings (fixed in v4.2.1).
    • Fix:
      // Avoid:
      $mock->shouldReceive('method')->once();
      
      // Use:
      $mock->shouldReceive('method')->once();
      
  3. PHPUnit Version Mismatches

    • TestBench Core does not support PHPUnit 13 due to volatility. Stick to PHPUnit 12 for stability.
    • Error: Class 'GrahamCampbell\TestbenchCore\Traits\MockeryTrait' not found may occur if PHPUnit is misconfigured. Ensure phpunit/phpunit is installed via Composer.
  4. Laravel Version Gaps

    • TestBench Core v4.3 supports Laravel 8–13, but v3.4 only supports up to Laravel 9. Check the compatibility table before upgrading.
  5. Facade Root Assumptions

    • FacadeTrait assumes the facade resolves to a single class. For multi-binding facades, manually resolve the binding:
      $this->app->bind('facade', function () {
          return new CustomFacadeRoot();
      });
      

Debugging Tips

  1. Mockery Not Working?

    • Ensure MockeryTrait is loaded before TestCase. Use use statements at the top of your test class.
    • Debug: Add Mockery::close() in tearDown() to reset mocks:
      protected function tearDown(): void
      {
          Mockery::close();
          parent::tearDown();
      }
      
  2. Static Method Conflicts

    • If you override getFacadeAccessor() statically but Laravel’s facade uses instance methods, add a fallback:
      protected static function getFacadeAccessor()
      {
          return static::getFacadeRoot()::getFacadeAccessor();
      }
      
  3. Service Provider Not Found

    • Verify getServiceProviderClass() returns the fully qualified class name (e.g., 'App\Providers\AuthServiceProvider').
    • Debug: Use dd(app()->getProviders()) to list loaded providers.

Extension Points

  1. Custom Traits

    • Extend existing traits to add domain-specific testing logic:
      trait CustomAssertionsTrait
      {
          public function assertJsonApiResponse($response, $data)
          {
              $this->assertEquals(200, $response->status());
              $this->assertArraySubset($data, $response->json());
          }
      }
      
  2. Mockery Helpers

    • Add helper methods to MockeryTrait for common patterns:
      protected function mockModel($model, $data = [])
      {
          $mock = $this->mock($model);
          $mock->shouldReceive('getAttribute')
              ->withArgs(function ($name) use ($data) {
                  return isset($data[$
      
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.
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
anil/file-picker
broqit/fields-ai