I'm new to testing in Laravel and I used to think that unit tests and feature tests were the same thing.
But now I realize there's a big difference between them.
Can someone please explain—preferably with examples—what exactly is the difference between unit tests and feature tests in Laravel? When should I use one over the other?
I tried writing some tests in Laravel 11 using both
php artisan make:test with the --unit flag and without it.
I expected both types of tests to work the same way since they looked similar at first. But when I ran them, I noticed they behave differently, especially when interacting with the database or HTTP routes.
I’m confused about which type to use for what purpose.
Use unit tests when you want fast, isolated tests for internal logic.
Use feature tests when testing real-world flows through your app that may depend on routing, middleware, or the database.
Purpose: Test small, isolated pieces of logic (usually classes or methods).
Located in: tests/Unit
How they work: They don’t load the full Laravel framework or handle things like database, routes, middleware, etc.
Use Case: Testing business logic, helper classes, service classes, etc.
// tests/Unit/PriceCalculatorTest.php
use Tests\TestCase;
class PriceCalculatorTest extends TestCase
{
public function test_discount_is_applied_correctly()
{
$calculator = new \App\Services\PriceCalculator();
$result = $calculator->applyDiscount(100, 10); // 10%
$this->assertEquals(90, $result);
}
}
Purpose: Test the application's full stack (routes, controllers, middleware, database, etc.)
Located in: tests/Feature
How they work: They boot the Laravel framework and simulate real user behavior (like submitting forms or visiting pages).
Use Case: Testing HTTP requests, database interaction, full flow of a feature.
// tests/Feature/UserRegistrationTest.php
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class UserRegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_register()
{
$response = $this->post('/register', [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$response->assertRedirect('/home');
$this->assertDatabaseHas('users', ['email' => 'john@example.com']);
}
}