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
No configuration or service provider registration is required.
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
}
}
Key Entry Points:
MockeryTrait to mock services, repositories, or facades without manual setup.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);
}
}
partialMock() for partial mocking of bound services.FacadeTrait to test facade interactions without instantiating underlying classes.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');
}
}
getFacadeAccessor() to specify the binding key for your facade.ServiceProviderTrait to test service provider registrations and bindings.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')
);
}
}
assertServiceBound() to verify bindings exist before testing.$this->assertArraySubset(['id' => 1], $userData); // Check if subset exists
$this->assertInternalType('array', $response->data); // Strict type checking
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');
}
}
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());
}
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);
}
Static Method Changes (v4.0+)
getFacadeAccessor() in FacadeTrait are now static. Update overrides:
// Old (pre-v4.0):
protected function getFacadeAccessor() { ... }
// New (v4.0+):
protected static function getFacadeAccessor() { ... }
Mockery Deprecation Warnings
MockeryTrait, ensure you’re using shouldReceive() (not shouldReceive('method') without parentheses) to avoid deprecation warnings (fixed in v4.2.1).// Avoid:
$mock->shouldReceive('method')->once();
// Use:
$mock->shouldReceive('method')->once();
PHPUnit Version Mismatches
Class 'GrahamCampbell\TestbenchCore\Traits\MockeryTrait' not found may occur if PHPUnit is misconfigured. Ensure phpunit/phpunit is installed via Composer.Laravel Version Gaps
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();
});
Mockery Not Working?
MockeryTrait is loaded before TestCase. Use use statements at the top of your test class.Mockery::close() in tearDown() to reset mocks:
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
Static Method Conflicts
getFacadeAccessor() statically but Laravel’s facade uses instance methods, add a fallback:
protected static function getFacadeAccessor()
{
return static::getFacadeRoot()::getFacadeAccessor();
}
Service Provider Not Found
getServiceProviderClass() returns the fully qualified class name (e.g., 'App\Providers\AuthServiceProvider').dd(app()->getProviders()) to list loaded providers.Custom Traits
trait CustomAssertionsTrait
{
public function assertJsonApiResponse($response, $data)
{
$this->assertEquals(200, $response->status());
$this->assertArraySubset($data, $response->json());
}
}
Mockery Helpers
MockeryTrait for common patterns:
protected function mockModel($model, $data = [])
{
$mock = $this->mock($model);
$mock->shouldReceive('getAttribute')
->withArgs(function ($name) use ($data) {
return isset($data[$
How can I help you explore Laravel packages today?