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.
Installation:
composer require --dev graham-campbell/testbench-core:^4.3
First Use Case:
Extend your test class with Illuminate\Foundation\Testing\TestCase (Laravel’s base test case) and add the desired trait (e.g., MockeryTrait or ServiceProviderTrait).
Example:
use GrahamCampbell\TestbenchCore\Traits\MockeryTrait;
use Illuminate\Foundation\Testing\TestCase;
class UserTest extends TestCase
{
use MockeryTrait;
public function test_mocked_service()
{
$mock = $this->mock('App\Services\UserService');
$mock->shouldReceive('fetchUser')->once()->andReturn(['id' => 1]);
$this->assertEquals(['id' => 1], $mock->fetchUser());
}
}
Where to Look First:
MockeryTrait, FacadeTrait, and ServiceProviderTrait for core testing needs.Mocking Services:
Use MockeryTrait to mock Laravel services, repositories, or external APIs.
$mock = $this->mock('App\Contracts\UserRepository');
$mock->shouldReceive('findById')->with(1)->andReturn(new User());
mock() over partialMock() for strict contract testing.Testing Facades:
Leverage FacadeTrait to verify facade interactions without instantiating underlying classes.
$this->assertEquals('expected', Facade::getFacadeRoot()->method());
getFacadeAccessor() to inspect bound services directly.Service Provider Testing:
Extend ServiceProviderTrait to test bindings, boot methods, and registrations.
$provider = new MyServiceProvider($this->app);
$this->assertTrue($provider->registers('binding'));
MockeryTrait to stub dependencies in providers.Assertions:
Use Laravel-specific assertions like assertArraySubset or assertInternalType.
$this->assertArraySubset(['id' => 1], $user->toArray());
$this->assertInternalType('array', $response->json());
TestCase Setup:
Override createApplication() in your test class to bootstrap Laravel with custom config/testing environments.
protected function createApplication()
{
$app = require __DIR__.'/../../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
Database Testing:
Use Laravel’s built-in RefreshDatabase trait alongside TestBench Core for seamless DB-driven tests.
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
use RefreshDatabase, MockeryTrait;
// ...
}
HTTP Testing:
Combine with Laravel’s HttpTests trait for API/route testing.
use Illuminate\Foundation\Testing\Concerns\InteractsWithHttp;
class UserApiTest extends TestCase
{
use InteractsWithHttp, MockeryTrait;
// ...
}
Custom Traits: Extend TestBench Core traits to add project-specific helpers.
trait CustomAssertions
{
public function assertResponseHasError(array $expectedErrors)
{
$response = $this->response;
$this->assertArraySubset($expectedErrors, $response->json()['errors']);
}
}
Mockery Deprecation:
MockeryTrait may trigger deprecation warnings in PHPUnit 12+ (fixed in V4.2.1).^4.2.1 or suppress warnings if using older versions.
$mock = $this->mock('Class', [], [], false, false, true, false);
Static Method Changes (V4.0+):
getFacadeAccessor() became static in V4.0, breaking older code.// Old (pre-V4.0)
$this->getFacadeAccessor();
// New (V4.0+)
FacadeTrait::getFacadeAccessor();
PHPUnit Version Mismatch:
composer.json:
"require-dev": {
"phpunit/phpunit": "^12.0"
}
Service Provider Traits:
getServiceProviderClass() no longer accepts $app as a parameter (V4.0+).// Old
$providerClass = $this->getServiceProviderClass($app, 'App\Providers\MyProvider');
// New
$providerClass = ServiceProviderTrait::getServiceProviderClass('App\Providers\MyProvider');
Facade Root Access:
getFacadeRoot() may return null if the facade isn’t bound.$root = FacadeTrait::getFacadeRoot();
$this->assertNotNull($root, 'Facade not bound');
Mockery Debugging: Enable Mockery’s verbose output to diagnose stubbing issues:
Mockery::getConfiguration()->setVerbose(true);
Service Container Dumps: Inspect bindings with:
$this->app->bindings();
Test Isolation:
Use setUp() and tearDown() to reset state between tests:
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
Custom Traits: Create project-specific traits by extending TestBench Core’s base traits. Example:
trait ApiResponseAssertions
{
use MockeryTrait;
public function assertApiSuccess($response, $expectedData = [])
{
$this->assertEquals(200, $response->status());
$this->assertArraySubset($expectedData, $response->json());
}
}
Test Helpers: Add static helper methods to your test base class:
abstract class BaseTestCase extends TestCase
{
protected static function createTestUser()
{
return User::factory()->create(['email' => 'test@example.com']);
}
}
Test Data Factories: Combine with Laravel’s factories for realistic test data:
$user = User::factory()->create();
$this->mock('App\Services\AuthService')
->shouldReceive('getUser')
->andReturn($user);
Parallel Testing:
Use PHPUnit’s --parallel flag with TestBench Core for faster test suites:
vendor/bin/phpunit --parallel
setUp() to reduce test initialization time.assertArraySubset instead of assertEquals for large arrays to skip deep comparisons.How can I help you explore Laravel packages today?