Napo7's avatar
Level 15

Lazy Loading with shouldBeStrict not being catched on tests

On my latest projet on Laravel 10.31, I have in my AppServiceProvider, Model::shouldBeStrict();, so without any env. condition.

I have a bunch of tests (I TDD all of my code, so every endpoint is tested.

I frequently encounter a problem : testing is allright, no any error, but in production (or even my own dev machine, with env=local), I face errors because of models are lazy loaded.

Of course, I do correct those errors by adding "with()" on my queries, but I can't understand why is the test passing without lazy loading errors !?

Have anyone faced such issue ?

0 likes
2 replies
LaryAI's avatar
Level 58

It sounds like you're encountering an issue where your tests are not catching lazy loading issues that occur when Model::shouldBeStrict(); is enabled in your AppServiceProvider. This is likely because your tests are not running with the same configuration as your production or development environments.

To ensure that your tests catch lazy loading issues, you need to make sure that the shouldBeStrict mode is enabled during testing. You can do this by setting up your test environment to mimic your production or development environment as closely as possible.

Here's what you can do:

  1. Ensure that Model::shouldBeStrict(); is called during the setup of your tests. You can do this in the setUp method of your test class or in a test-specific service provider.

  2. Make sure that your .env.testing file (or whichever environment file your tests are using) does not override settings that would disable strict loading.

  3. If you're using Laravel's built-in testing features, such as RefreshDatabase, ensure that they are not interfering with the strict loading settings.

Here's an example of how you might set up a test to ensure shouldBeStrict is enabled:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Model;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        // Enable strict loading for all tests
        Model::shouldBeStrict();
    }

    /** @test */
    public function it_catches_lazy_loading()
    {
        // Your test code here
    }
}

By doing this, you're ensuring that any lazy loading performed by your models will throw an exception during testing, just as it would in your production or development environment.

If you're still not catching lazy loading issues, you may want to review your test cases to ensure they are comprehensive enough to cover the scenarios where lazy loading might occur. Remember that tests can only catch issues that they are designed to test for, so it's important to have thorough test coverage for your application's functionality.

Napo7's avatar
Level 15

Nice try Mr Robot, but's I think I finally found my problem ! Digging into laravel source code, I found out that Lazy Loading is only triggered when you try to lazy load relations on MORE THAN ONE ITEM at a time. So, if my relations are 1 post -> 1 comment -> 1 author, it will never trigger lazy loading error. That's how the test is setup. When in production, if one of the relations has more than one occurence (ie. 2 comments), it will trigger an error because more than 1 author will be lazy loaded !

So, to summarize, a new rule of thumb should be : whenever your code should handle many items, your test MUST always generate more than one item !

1 like

Please or to participate in this conversation.