Сбой тестов PHPUnit после добавления ViewServiceProvider для совместного использования данных в представлениях

#laravel #phpunit

#laravel #phpunit

Вопрос:

Я относительно новичок в тестировании, поэтому, пожалуйста, простите меня, если это глупый вопрос.

Все мои тесты терпят неудачу после того, как я добавил ViewServiceProvider для обмена данными с представлениями.

Ошибка: IlluminateDatabaseQueryException : SQLSTATE[HY000]: General error: 1 no such table: policies (SQL: select "name", "slug" from "policies")

В моих тестах используется функция обновления базы данных:

 namespace TestsFeature;

use IlluminateFoundationTestingRefreshDatabase;
use TestsTestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    ...
}
 

Вот пример ViewServiceProvider:

 namespace AppProviders;

use AppModelsPolicy;
use IlluminateSupportServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    public function register(): void{...}

    public function boot(): void
    {
        view()->share('policies', Policy::all(['name', 'slug']));
    }
}
 

Каждый работает при просмотре сайта на интерфейсе. Я что-то упустил? Почему тесты не выполняются?

Я буду признателен за предложения о том, как сделать так, чтобы тесты прошли успешно.

Редактировать
То, что сказал @Donkarnash, имеет полный смысл, но это также сбивает с толку, потому что, согласно документам:

Итак, что, если нам нужно зарегистрировать составителя представлений в нашем поставщике услуг? Это должно быть сделано в методе загрузки. Этот метод вызывается после регистрации всех других поставщиков услуг, что означает, что у вас есть доступ ко всем другим службам, которые были зарегистрированы платформой

См. https://laravel.com/docs/8.x/providers#the-boot-method

Комментарии:

1. Поставщик услуг загружается до запуска миграции, поэтому он не может найти политики таблиц

2. Спасибо @Donkarnash, есть идеи, как можно было бы пройти тесты?

3. Я думаю, что когда-то у меня была похожая ситуация, и я использовал грязный взлом кэширования. Это немного хрупко, но это сработало.

4. Что, если вы обернете код в if (! app()-> runningInConsole()) { view()-> share(‘policies’, Policy::all([‘name’, ‘slug’])); }; если это сработает, я напишу ответ

5. Да, я пробовал что-то подобное @mrhn, но затем Undefined variable возникают исключения. Я думаю, я могу добавить isset проверки для переменных в представлениях, но я не хочу этого делать только для того, чтобы мои тесты прошли. Я передаю больше, чем просто политики для представлений. Но если другого способа действительно нет, мне придется это сделать.

Ответ №1:

Я нашел решение. Создание компоновщика представлений решило проблему.

 namespace AppHttpViewComposers;

use AppModelsPolicy;
use IlluminateViewView;

class PolicyComposer
{
    public function compose(View $view): void
    {
        $view->with('policies', Policy::all(['name', 'slug']));
    }
}
 

Затем я сослался на композитора в ViewServiceProvider

 namespace AppProviders;

use AppModelsPolicy;
use IlluminateSupportServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    public function register(): void{...}

    public function boot(): void
    {
        view()->composer('*', PolicyComposer::class);
    }
}