Testing in Laravel
Laravel provides excellent testing support out of the box. The framework includes PHPUnit for running tests and gives you a variety of helpful assertion methods for testing your application.
Tests live in the tests directory. Laravel organizes tests into two categories: feature tests and unit tests.
Feature vs Unit Tests
Unit tests test a small, isolated piece of code. They do not boot the Laravel framework and are fast to run. Feature tests bootstrap the entire application and test how multiple pieces work together.
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class MathTest extends TestCase
{
public function test_addition()
{
$this->assertEquals(4, 2 + 2);
}
}
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Models\User;
class UserRegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_register()
{
$response = $this->post('/register', [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'secret123',
'password_confirmation' => 'secret123',
]);
$response->assertStatus(200);
$this->assertDatabaseHas('users', [
'email' => 'john@example.com',
]);
}
}
The RefreshDatabase trait resets your database after each test, so tests never interfere with each other.
Testing HTTP Requests
Laravel provides a fluent API for making HTTP requests in tests. You can test GET, POST, PUT, PATCH, and DELETE requests with ease.
public function test_post_creates_article()
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/api/articles', [
'title' => 'My First Article',
'body' => 'This is the content.',
]);
$response->assertStatus(201);
$response->assertJsonFragment([
'title' => 'My First Article',
]);
}
The actingAs method authenticates a user without going through the login flow. This makes testing authenticated routes simple.
use Illuminate\Support\Facades\Http;
public function test_api_returns_data()
{
Http::fake([
'api.external.com/*' => Http::response(['status' => 'ok'], 200),
]);
$response = $this->getJson('/api/data');
$response->assertOk();
}
Http::fake lets you mock external API calls so your tests are fast and reliable.
Using Factories in Tests
Model factories generate fake data for your models. They are perfect for creating test records quickly.
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
protected $model = User::class;
public function definition()
{
return [
'name' => $this->faker->name,
'email' => $this->faker->unique()->safeEmail,
'password' => bcrypt('password'),
];
}
}
In your tests, create multiple records easily with the times() method.
public function test_pagination_works()
{
User::factory()->count(25)->create();
$response = $this->get('/users');
$response->assertOk();
}
Factories keep your tests clean and readable without hardcoded data.
Running Your Tests
Run your entire test suite with a single command. PHPUnit discovers and executes all test files automatically.
php artisan test
vendor/bin/phpunit
vendor/bin/phpunit --filter test_user_can_register
The --filter flag lets you run a specific test by name. This is helpful when debugging a single failing test. Laravel also provides detailed test output showing pass and fail counts.