clarg18's avatar

Sharing model with all views via ASP breaks unit tests

Hello,

Since I added the following to my AppServiceProvider.php class:

    public function boot()
    {
        View::share('statuses', Status::all()); 
    }

All of my unit tests now error out with the following returned from phpunit:

57) Tests\Feature\StaffTest::staffValidationActiveMustBoolean
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 no such table: statuses (SQL: select * from "statuses")

Caused by
PDOException: SQLSTATE[HY000]: General error: 1 no such table: statuses

My tests are using the RefreshDatabase trait and are configured to use sqlite in memory for the testing enviroment via phpunit.xml:

        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>

Is it possible to resolve this without deleting the call the View facade every time?

0 likes
7 replies
tykus's avatar

The table hasn't been migrated (and populated?) before the AppServiceProvider boots, so there is no table whenever it tries to share the data. You could check if you are running unit tests before attempting to use the model:

View::share('statuses', $this->app->runningUnitTests() ? collect() : Status::all());

But it might be better to find a solution where you are not reliant on the database in a Service Provider.

clarg18's avatar

@tykus

Thank you, is there a better way I should be sharing a model to all views that does not break migrating/unit tests?

Sti3bas's avatar

@glenuk do you tried view composer?

View::composer('*', function ($view) {
   $view->with('statuses', Status::all());
});
1 like
tykus's avatar
tykus
Best Answer
Level 104

It is always an awkward situation where you are working with an in-memory database for tests and also relying on the database so early in the application's lifecycle. For simple use cases, I would rely on the solution above, however, this would break down if you wanted to assert against some/all of that data being present in the view (in the context of a test).

The view composer approach is more friendly to testing because they are called only whenever the view is actually rendered, so the application has bootstrapped without relying on the database.

tykus's avatar

The view composer could be registered in the AppServiceProvider, yes.

The main take away is when the Eloquent query would be executed, i.e. whenever a view is rendered, and not whenever the App is bootstrapping (as was the case with View::share inside the same sservice provider).

Please or to participate in this conversation.