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

Lumen Testing Laravel Package

albertcht/lumen-testing

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package in your require-dev block and let Composer pull the matching testing traits:

composer require --dev vendor/package:^1.1

Nothing needs publishing or bootstrapping — the traits are consumed directly by your test classes. Start by opening src/Concerns/ and reading the two files touched in v1.1, InteractsWithAuthentication.php and MocksApplicationServices.php. Those two files define almost the entire day-to-day surface area of the package: authentication helpers and queue/job mocking.

Your first practical use case is the classic "protected route" test, which is where most teams get value on day one:

use Vendor\Package\Testing\Concerns\InteractsWithAuthentication;

class DashboardTest extends TestCase
{
    use InteractsWithAuthentication;

    public function test_guests_are_redirected(): void
    {
        $this->get('/dashboard')->assertRedirect('/login');
    }

    public function test_members_see_the_dashboard(): void
    {
        $this->be(User::factory()->create());

        $this->get('/dashboard')->assertOk();
    }
}

If you have existing tests using $this->actingAs($user), they keep working — be() is the shorter alias added in v1.1 and is the one to standardise on.

Implementation Patterns

Authentication helpers. Use be($user) for the common case and keep actingAs($user, $guard) when you need to pin a non-default guard. Because be() mutates the test's authentication state rather than the request, you can call it once at the top of a test and every subsequent $this->get() in that test is authenticated — which makes multi-step flows (login → visit → post → assert) read cleanly. Pair it with a guest assertion early in the test so a broken be() fails loudly instead of silently testing an authenticated route.

Job mocking. expectsJobs() and withoutJobs() give you two distinct levers:

public function test_registration_dispatches_welcome_email(): void
{
    $this->expectsJobs(SendWelcomeEmail::class);

    $this->post('/register', [...])->assertRedirect('/home');
}

public function test_listing_page_does_not_dispatch_reports(): void
{
    $this->withoutJobs();

    $this->get('/reports')->assertOk();
}

expectsJobs() is the assertion form — it fails if the job is not dispatched, so reach for it when the dispatch is the behaviour under test. withoutJobs() is the isolation form — it prevents dispatch entirely, so reach for it when the job is incidental and you just want a fast, side-effect-free test. Don't mix them in the same test; withoutJobs() will swallow the very dispatch expectsJobs() is waiting for.

Console and container support (new in v1.1). This is the release that makes the package viable for tests that previously needed raw Laravel test-case plumbing. Assert Artisan commands directly:

$this->artisan('report:generate --month=03')
    ->expectsOutput('Reports generated')
    ->assertExitCode(0);

And resolve or rebind container entries inside a test without manually booting the application:

$this->instance(PaymentGateway::class, $fakeGateway);

$this->assertSame($fakeGateway, $this->app->make(PaymentGateway::class));

For command tests that touch the database, prefer DatabaseTransactions over RefreshDatabase in the same class — a long-running console test that migrates twice is the most common source of slow suites built with this package.

Exception handling trait. v1.1 adds a dedicated trait for toggling exception handling, which is cleaner than calling $this->withoutExceptionHandling() in individual methods:

use Vendor\Package\Testing\Concerns\HandlesExceptions;

class CheckoutTest extends TestCase
{
    use HandlesExceptions;

    protected bool $handleExceptions = false;
}

Use false for the class when you care about stack traces (unit-ish tests of controllers), and leave handling on for the feature tests that assert on rendered 4xx/5xx responses. Mixing the two modes in one class is a smell — split the class.

Gotchas and Tips

  • v1.1 is additive. All four items are features or missing-method additions (be(), expectsJobs(), withoutJobs(), exception trait), with no removals or signature changes. Upgrading from v1.0 is a drop-in — but bump your require-dev constraint and run the suite once to catch trait-name collisions in your own base TestCase.
  • be() depends on the guard resolving a user. If your User model doesn't implement Authenticatable, or you've configured a non-Eloquent provider, be() will fail in a way that looks like a routing problem. Assert $this->assertAuthenticated() mid-test when the failure mode is unclear.
  • Job mocking is not queue faking. expectsJobs()/withoutJobs() intercept dispatches; they do not give you access to the queue payload, chained jobs, or assertPushed style callbacks. As soon as you need to inspect what was queued (properties, delays, chains), drop down to Queue::fake() in that test rather than fighting the abstraction.
  • Notifications and events are not covered by the job mockers. A ShouldQueue notification fired from a listener will still run unless you fake notifications separately — a common source of "why is my test slow" investigations.
  • Exception handling off changes assertion semantics. With handling disabled, a validation failure raises ValidationException instead of returning a 302 with errors in the session. Tests written against the redirect will break when you toggle the trait — decide per test file and be consistent.
  • Container rebinding leaks across tests in the same class if you bind on $this->app from setUp() without a fresh application per test. Bind inside the test method, or override setUp() carefully.
  • Trait ordering matters in your base TestCase. If you already use MocksApplicationServices from Laravel itself, aliasing or explicit insteadof may be needed — method-name collisions here surface as fatal errors, not silent overrides.
  • Extension point: the concerns are plain traits, so composition is the intended customisation path. Wrap them in your own AppTestCase trait that sets sensible defaults (withoutJobs(), exception handling off, a beCustomer() helper) rather than editing vendor code — this survives package upgrades and keeps the intent visible.
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.
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
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource