anlutro/l4-testing
anlutro/l4-testing provides testing helpers for Laravel 4 applications, including base test cases and utilities for database transactions, mocking, and common framework services, helping developers write cleaner unit and integration tests with less boilerplate.
Install as a dev dependency so it never ships to production:
composer require --dev anlutro/l4-testing
The package is intentionally tiny — there is no service provider, no config file to publish, and no Artisan command. Start by reading src/ directly; the entire surface area is one or two base classes (typically a TestCase that extends PHPUnit_Framework_TestCase and boots the Laravel 4 application container). That is the whole package, so "where to look first" is literally the source file you'll be extending.
The first use case is replacing the hand-rolled bootstrap you'd otherwise copy into app/tests/TestCase.php. Create your project test base class by extending the package class, then have your individual test classes extend yours:
// app/tests/TestCase.php
class TestCase extends Anlutro\LaravelTesting\TestCase
{
public function createApplication()
{
$unitTesting = true;
$testEnvironment = 'testing';
return require __DIR__.'/../../bootstrap/start.php';
}
}
Then write your first real test against a route or a model:
class UserTest extends TestCase
{
public function testIndexReturnsOk()
{
$response = $this->call('GET', '/users');
$this->assertEquals(200, $response->getStatusCode());
}
}
Run it with vendor/bin/phpunit from your project root, pointing at app/tests. If the app boots and the assertion runs, you've validated the integration. The value here is not features — it's that the bootstrapping and teardown semantics are already solved so you don't re-derive them per project.
One application instance per test, torn down after. The base class should call createApplication() in setUp() and null it out in tearDown(). Follow this contract in subclasses: never reuse a booted app across test methods. If you add your own setUp() overrides, always call parent::setUp() first.
Per-test database isolation. The most common day-to-day pattern with Laravel 4 testing bases is wrapping each test in a transaction. If the package base class doesn't include it, add it to your own TestCase:
public function setUp()
{
parent::setUp();
$this->app['db']->beginTransaction();
}
public function tearDown()
{
$this->app['db']->rollback();
parent::tearDown();
}
This keeps the suite fast and makes tests order-independent — a property you lose the moment someone forgets the rollback.
Arrange against the container, assert against the response. Structure tests as: seed via Eloquent/repositories, exercise via $this->call(...) or by resolving services out of $this->app, then assert on the response object or the database. This mirrors the request lifecycle well and catches the facade/container wiring problems that unit tests miss.
Use $this->app as the seam for test doubles. For anything hitting the network, filesystem, or mailer, bind a fake into the container before exercising the code path:
$this->app->instance('Mailer', $mock);
Because the base class exposes the booted container, this pattern consistently works across packages — no per-package mocking helpers required.
Group slow integration tests. Mark database- and HTTP-touching tests with @group integration and keep fast unit tests in a separate group. Run phpunit --exclude-group integration in your pre-commit hook and the full suite in CI. Laravel 4 suites get slow quickly, and the package gives you the container without imposing a speed strategy.
Keep a single shared base and layer from it. Resist extending TestCase directly in every test file. Create IntegrationTestCase and UnitTestCase layers on top of the package base so you can tune bootstrapping per category without rewriting hundreds of files later.
Laravel 4 is ancient — pin everything. This package targets illuminate/* 4.x and PHPUnit ~3.7/4.x. Composer will happily resolve conflicts in strange ways if you're mixing it into a newer app; it won't work at all on Laravel 5+. Treat it as a period-specific tool, and commit a composer.lock so the environment is reproducible.
PHPUnit version drift is the #1 debug target. PHPUnit_Framework_TestCase and the setUp() signature changed in PHPUnit 5/6. If tests fail with "class not found" or signature errors, check phpunit --version before touching your test code.
Bootstrapping order matters more than you think. bootstrap/start.php runs the start.php bootstrappers which include path detection and environment detection. In CLI, $unitTesting and $testEnvironment must be set before requiring it — set them as shown above, not after. Forgetting this is why people see "production" database writes from tests.
Transaction rollback doesn't cover everything. If a test writes through a separate connection, invokes queue workers, or uses DDL (Schema::create auto-commits in MySQL), the rollback won't undo it. Isolate those tests, use SQLite in-memory for schema-heavy suites, or reset the schema explicitly in tearDown().
Facade mocks leak between tests. Mail::shouldReceive(...) swaps the underlying instance in the container. If tearDown() doesn't rebuild or clear the app, a later test can silently hit a leftover mock. Rely on a fresh app per test and never share $this->app across methods.
Debugging a failing boot: reproduce the exact bootstrap in a tinker-style script (php -r "require 'bootstrap/start.php';"). If the app initializes fine outside PHPUnit but fails inside, the difference is almost always environment variables or working directory — PHPUnit runs relative to its config location, so path-dependent bootstrappers break.
Extension points are just PHP inheritance. There's no event system here. To customize behavior, override createApplication() (most common), setUp()/tearDown(), or add helper assertion methods on your intermediate base class. Because the package is unopinionated, it composes cleanly with Mockery, Faker, and Laravel 4's own Illuminate\Foundation\Testing traits — you're not fighting a framework on top of a framework.
Low maintenance signal. With 13 stars and zero dependents, expect no upstream fixes. Fork it into app/tests/Support/ if you need to modify the base class; depending on a require-dev package that may vanish from Packagist is a poor trade for ~100 lines of bootstrap code.
How can I help you explore Laravel packages today?