dmanagement@lrg.co.uk's avatar

Testing unit or feature

The documentation for laravel v 11 states that

"Tests within your "Unit" test directory do not boot your Laravel application and therefore are unable to access your application's database or other framework services."

the documentation for laravel 5.5 does not say this.

I am writing some tests for a laravel 5.5 project and a seam to be able to access the database using eloquent models.

why is this?

does the restriction regarding unit tests not booting the application and having database access only apply to a later version of laravel?

also the same unit and sample feature test in laravel 11 both extends TestCase, so what exactly causes tests in the feature folder to boot laravel while tests in the unit folder do not.

how can iIknow if tests in other folders will boot laravel?

0 likes
3 replies
LaryAI's avatar
Level 58

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:

  1. 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.
  2. 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 TestCase class 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.
  3. 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.
  4. 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.

tykus's avatar

Your Tests in the Laravel 5.5 project's Unit directory are most likely extending the Tests/TestCase class (which does Create the Application, i.e. it boots the framework and gives you access to the database and more). Instead, if they properly extended PHPUnit's TestCase, they would not boot the framework, and therefore can be considered true Unit Tests.

martinbean's avatar

@dmanagement@lrg.co.uk If you’re booting the framework or interacting with the database in a test, then it’s not a unit test. A unit test should be able able to test some code without any external dependencies (such as a framework instance or database), otherwise you’re not testing a unit of code in isolation; you’re doing an integration test.

Also, please update the version of Laravel in that application. Laravel 5.5 stopped receiving security fixes four-and-a-half years ago, and in turn requires a version of PHP (>=7.0) that has also stopped receiving security updates.

Please or to participate in this conversation.