In Laravel, the distinction between unit and feature tests is more about convention and best practices rather than strict enforcement by the framework. Here's a breakdown of the concepts and why you might be seeing different behaviors:
-
Unit Tests vs. Feature Tests:
- Unit Tests: These are meant to test individual pieces of code, such as methods or classes, in isolation. They should not depend on the framework's services, like the database, and typically do not require booting the Laravel application.
- Feature Tests: These are designed to test larger portions of your application, often involving multiple components and interactions. They usually require booting the Laravel application to access the full stack, including the database.
-
Laravel 5.5 vs. Laravel 11:
- In Laravel 5.5, there was less emphasis on enforcing the separation between unit and feature tests. This means you could technically access the database in unit tests if you extended the
TestCaseclass that bootstraps the application. - In Laravel 11, the documentation and best practices have evolved to encourage a clearer separation. The framework itself doesn't enforce this separation, but it's recommended to follow it for better test design.
- In Laravel 5.5, there was less emphasis on enforcing the separation between unit and feature tests. This means you could technically access the database in unit tests if you extended the
-
Bootstrapping the Application:
- The key difference in whether a test boots the Laravel application lies in the base test class it extends. If your test class extends a base class that bootstraps the application (like
Illuminate\Foundation\Testing\TestCase), it will have access to the full application, including the database. - By default, feature tests extend a base class that bootstraps the application, while unit tests do not. However, this is a convention, and you can change it by modifying the base class your tests extend.
- The key difference in whether a test boots the Laravel application lies in the base test class it extends. If your test class extends a base class that bootstraps the application (like
-
Determining if a Test Boots Laravel:
- Check the base class your test extends. If it extends a class that bootstraps the application, it will have access to the full Laravel stack.
- You can also look at the setup methods in your test class. If they call methods like
parent::setUp()from a class that bootstraps the application, then the application is being booted.
Here's an example of how you might structure a feature test in Laravel:
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
public function test_example()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
And a unit test might look like this:
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
In summary, the behavior you're observing is due to the conventions and best practices that have evolved over different Laravel versions. It's important to follow these conventions to ensure your tests are well-structured and maintainable.