Weave 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

alt-three/testbench

A lightweight testing harness for Laravel packages, providing a bootstrapped application instance with service providers, configuration, and helpers so you can write fast, reliable package tests without a full application skeleton.

View on GitHub
Deep Wiki
Context7

Getting Started

AltThree/TestBench is a small collection of PHPUnit traits that you use inside your application's base tests/TestCase.php. It is not a testing framework of its own; it assumes a standard Laravel test suite and only adds helper methods on top.

  1. Check compatibility before installing. The package is archived and its last release was August 2020, so it was written against the Laravel 5.x/6.x and PHPUnit 7/8 era. On Laravel 9+ you will almost certainly hit a Composer resolution failure on phpunit/phpunit or illuminate/support constraints. If you are evaluating it for a legacy app, pin it explicitly:

    composer require --dev alt-three/testbench:^1.0
    

    Do not add it to a new project — see Gotchas below.

  2. Read src/ first. The whole package is a handful of trait files, one per file, each with a small number of public methods. There is no service provider, no config file, and effectively no runtime surface beyond the traits themselves. Open each trait and read the method bodies — you can absorb the entire package in a few minutes, and that is the most reliable documentation you will get, since the README is thin and the repo is frozen.

  3. Wire it into your base test case. Traits are consumed by composition, typically once, in the base class every test extends:

    namespace Tests;
    
    use AltThree\TestBench\SomeTrait; // whichever trait you need
    use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
    
    abstract class TestCase extends BaseTestCase
    {
        use CreatesApplication;
        use SomeTrait;
    
        protected function setUp(): void
        {
            parent::setUp();
            // trait initialization, if the trait exposes a hook
        }
    }
    
  4. First use case. Pick the single trait whose helpers map to something you already do by hand — most commonly the mocking/spy helpers around Laravel's container-bound services (events, mailer, bus, queue). Write one test that calls the trait helper and asserts on the resulting Mockery expectation, then delete your hand-rolled equivalent. That one-for-one swap is the entire value proposition of the package.

Implementation Patterns

Compose at the base class, use at the leaf. Add traits only to Tests\TestCase, not to individual test classes. Because these are plain PHPUnit traits, a second use of the same trait in a child class silently shadows the parent's copy and you lose any setUp/tearDown bootstrapping the trait performs. One import site keeps behaviour predictable.

Pair with Mockery, don't replace it. The helpers are thin wrappers that resolve a binding from the container and register expectations on it. The idiomatic flow is:

public function testOrderIsDispatched(): void
{
    $this->expectsEvents(OrderPlaced::class); // or the trait's equivalent helper

    $this->post('/orders', ['sku' => 'ABC'])->assertStatus(201);
}

Keep your existing Mockery::close() in tearDown() (Laravel's base class already does this) and let the trait handle only the container wiring.

Use it to replace withoutEvents() / facade swaps. If you currently do Event::fake() or Bus::fake() in every test that touches a service, the traits are a cleaner place to centralise "fake this, assert it fired, restore it" so individual tests stay short. This is the pattern most worth copying.

Adopt as a reference implementation rather than a dependency. Given the archive status, the highest-leverage pattern is: read the trait, copy the 20–40 lines into your own tests/Concerns/ directory, and own it. You get the same ergonomics with no dead dependency and full control when Laravel's testing APIs shift.

Legacy-suite migration path. If you are modernising an app that already depends on the package, replace each trait with the corresponding Illuminate\Foundation\Testing\* capability (RefreshDatabase, WithoutMiddleware, Event::fake(), Http::fake(), Queue::fake()) one at a time, running the suite after each swap. Do not attempt a single big-bang removal; trait method collisions make failures hard to attribute.

Gotchas and Tips

  • Archived means no security or framework patches. No Laravel 9/10/11 support, no PHP 8.1+ enum/readonly fixes, and no PHPUnit 9/10 lifecycle compatibility. On modern PHPUnit the setUp()/tearDown() signatures are void-typed and final in places; a trait declaring untyped versions will fatal with "declaration must be compatible". Expect to edit the trait or skip it entirely.
  • Zero dependents is a signal, not a coincidence. Six stars and no downstream users means edge cases were never shaken out. Treat every helper as unverified code you are now responsible for.
  • Trait method collisions are silent. If your base TestCase (or Laravel's own TestCase) already defines a method with the same name, PHP resolves by precedence rules you will not enjoy debugging. Run php -r reflection over the base class, or simply grep the trait for method names before importing.
  • Container leakage between tests. Helpers that instance() a fake into the container can survive into later tests if the app is not rebuilt per test. Confirm CreatesApplication is in play and that refreshApplication() runs; if a fake "sticks", that is almost always the cause.
  • Ordering matters around parent::setUp(). If the trait stubs something the framework needs during boot (config, exception handler), calling it before parent::setUp() will produce confusing "class not found" or "facade root not set" errors. Default to initialising after parent::setUp() unless the trait's source clearly says otherwise.
  • Debugging: use phpunit --filter=YourTest --debug to see exactly where a trait-induced failure lands, and --stop-on-failure when a stub leaks. When a mock expectation reports "no matching handler", the trait probably registered it on a different container binding than the one your code resolves — check app()->bound() for both keys.
  • Extension points are just PHP. There is no config, no provider, no events. To change behaviour, override the trait method in your base TestCase (calling parent:: where useful) or fork the file. Forking is the recommended path at this point in the package's life.
  • Don't reach for it in greenfield work. Laravel's first-party testing utilities cover everything these traits did, are maintained against current PHPUnit, and are documented. The only defensible reason to touch this package today is maintaining an existing suite that already depends on it — and even then, plan the removal.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle