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.
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.
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.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.ShouldQueue notification fired from a listener will still run unless you fake notifications separately — a common source of "why is my test slow" investigations.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.$this->app from setUp() without a fresh application per test. Bind inside the test method, or override setUp() carefully.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.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.How can I help you explore Laravel packages today?