Migrer la base de données pour tester le schéma de Laravel
P粉722409996
P粉722409996 2023-08-26 17:09:54
0
2
471
<p><h1>问题</h1> <ul> <li>我正在使用 Laravel <code>8.83.23</code></li> <li>我有来自压缩迁移的模式转储文件,位于 <code>database\schema\mysql-schema.dump</code></li> <li>测试运行在测试数据库上,就像在 <code>database.php</code> 中一样</li> </ul> <pre class="brush:php;toolbar:false;">'testing' => [ 'driver' => 'mysql', 'host' => env('DB_TEST_HOST', '127.0.0.1'), 'port' => env('DB_TEST_PORT', '3306'), 'database' => env('DB_TEST_DATABASE', 'forge'), 'username' => env('DB_TEST_USERNAME', 'forge'), 'password' => env('DB_TEST_PASSWORD', ''), ],</pre> <ul> <li>在我压缩迁移之前,我的测试用例只使用了 <code>DatabaseMigrations</code> trait,并且测试数据库每次都会被重新创建,一切正常,以下是一个测试类的示例:</li> </ul> <pre class="brush:php;toolbar:false;">class SystemControllerTest extends TestCase { use WithFaker; use DatabaseMigrations; /** * @var User */ private $user; public function setUp(): void { parent::setUp(); //创建角色和数据 $this->seed(RoleAndPermissionSeeder::class); ... 等等</pre> <ul> <li>迁移被找到并执行,重新创建了数据库</li> <li>然后,我压缩了迁移,所以所有的迁移都被删除了,我得到了 <code>database\schema\mysql-schema.dump</code></li> <li><code>php artisan migrate</code> 通过命令行按预期工作,从转储文件中创建完整的数据库模式(它找到了它)</li> <li>然而,测试不再工作,因为出现了一个错误</li> </ul> <pre class="brush:php;toolbar:false;">SQLSTATE[42S02]: Base table or view not found: 1146 Table 'cinema_test.roles' doesn't exist (SQL: delete from `roles`)</pre> <ul> <li>当我在测试运行后检查 sql 测试数据库时,它是空的(只有表 <code>migrations</code> 被创建,而且是空的)</li> <li>即使在测试的设置中调用 <code>artisan migrate</code>,这个错误仍然存在:</li> </ul> <pre class="brush:php;toolbar:false;">public function setUp(): void { parent::setUp(); Artisan::call('migrate', array( '--database' => 'testing', '--force' => true)); //它在这里崩溃 $this->seed(RoleAndPermissionSeeder::class);</pre> <ul> <li><code>RoleAndPermissionSeeder</code> 只操作不存在的 sql 表,因此出现错误</li> <li>我甚至尝试了 <code>DatabaseMigrations</code>、<code>DatabaseTransactions</code> 和 <code>RefreshDatabase</code> traits,但都没有成功</li> <li>我如何填充数据库数据?我无法读取 <code>Artisan::call('migrate')</code> 命令的输出,所以我不知道那里发生了什么</li> <li><code>Artisan::call('migrate')</code> 的返回代码是 <code>0</code></li> <li>我是否可能遗漏了一些设置?</li> </ul></p>
P粉722409996
P粉722409996

répondre à tous(2)
P粉952365143

On dirait que lors des tests, il n'est pas possible d'exploiter une base de données en mémoire à l'aide d'un fichier de vidage de schéma

https://laravel.com/docs/9.x/migrations#squashing-migrations

Vous pouvez essayer ceci

DB::unprepared(file_get_contents("path/file.sql"));

Essayez-le uniquement en dernier recours. Personnellement, il est recommandé de migrer dans l'environnement de test. Si vous adoptez cette méthode, vous devez également ajouter une vérification de migration dans l'environnement de test

.
P粉821274260

J'ai enfin compris.

Cause du problème

Le problème est que l'environnement de test n'est pas configuré correctement. Je n'ai pas trouvé la cause exacte, mais j'ai trouvé comment configurer l'environnement de test pour que le fichier de vidage soit trouvé et chargé.

Comment détecter les erreurs

Ceci décrit les étapes que j'ai suivies pour trouver la solution.

Dans database.php j'ai copié la base de données de test au lieu de la base de données normale
  • Dans database.php j'ai la connexion à la base de données principale :
'mysql' => [
                'driver' => 'mysql',
                'url' => env('DATABASE_URL'),
                'host' => env('DB_HOST', '127.0.0.1'),
                'port' => env('DB_PORT', '3306'),
                'database' => env('DB_DATABASE', 'forge'),
                'username' => env('DB_USERNAME', 'forge'),
                'password' => env('DB_PASSWORD', ''),
                'unix_socket' => env('DB_SOCKET', ''),
                'charset' => 'utf8mb4',
                'collation' => 'utf8mb4_unicode_ci',
                'prefix' => '',
                'prefix_indexes' => true,
                'strict' => false,
                'engine' => null,
                'options' => extension_loaded('pdo_mysql') ? array_filter([
                    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                ]) : [],
            ],

et tester la connexion

'testing' => [
                    'driver' => 'mysql',
                    'host' => env('DB_TEST_HOST', '127.0.0.1'),
                    'port' => env('DB_TEST_PORT', '3306'),
                    'database' => env('DB_TEST_DATABASE', 'forge'),
                    'username' => env('DB_TEST_USERNAME', 'forge'),
                    'password' => env('DB_TEST_PASSWORD', ''),
                ],
  • Je vais testing连接数据复制到一个新的mysqlme connecter juste pour voir si j'obtiens les mêmes résultats sur la ligne de commande
  • Donc, le fichier ressemble maintenant à ceci
'mysql' => [
                'url' => env('DATABASE_URL'),
                'driver' => 'mysql',
                    'host' => env('DB_TEST_HOST', '127.0.0.1'),
                    'port' => env('DB_TEST_PORT', '3306'),
                    'database' => env('DB_TEST_DATABASE', 'forge'),
                    'username' => env('DB_TEST_USERNAME', 'forge'),
                    'password' => env('DB_TEST_PASSWORD', ''),
                'unix_socket' => env('DB_SOCKET', ''),
                'charset' => 'utf8mb4',
                'collation' => 'utf8mb4_unicode_ci',
                'prefix' => '',
                'prefix_indexes' => true,
                'strict' => false,
                'engine' => null,
                'options' => extension_loaded('pdo_mysql') ? array_filter([
                    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                ]) : [],
            ],
    
    /*'testing' => [
                    'driver' => 'mysql',
                    'host' => env('DB_TEST_HOST', '127.0.0.1'),
                    'port' => env('DB_TEST_PORT', '3306'),
                    'database' => env('DB_TEST_DATABASE', 'forge'),
                    'username' => env('DB_TEST_USERNAME', 'forge'),
                    'password' => env('DB_TEST_PASSWORD', ''),
                ],*/
  • Sur la console, j'ai couru php artisan:migrate
  • Fichier de dump de base de données trouvé et chargé
  • Donc, dans le cas normal, le fichier de vidage a été trouvé, mais dans le cas de test il n'a pas été trouvé
  • Après quelques recherches, j'ai modifié les paramètres de l'environnement de test dans phpunit.xml, je vais l'expliquer maintenant
Fichierphpunit.xml

phpunit.xml Ressemble à ceci (fichier complet non affiché ici) :

<server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
        <env name="DB_CONNECTION" value="testing"/>     
    </php>
</phpunit>
  • Nous pouvons donc voir que la connexion à la base de données de test est définie comme un test unitaire
  • Sur le Web, j'ai trouvé des conseils pour simplement configurer les tables de la base de données au lieu de modifier toute la connexion pour les tests, car c'est plus facile ainsi
  • J'ai essayé quelque chose comme ça, alors phpunit.xml est devenu
<server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
        <env name="DB_DATABASE" value="cinema_test"/>   
    </php>
</phpunit>
  • J'ai supprimé la connexion de test de database.php中删除了测试连接,并从.env et supprimé les variables obsolètes pertinentes du fichier .env
  • Cela résout le problème, désormais le fichier de dump est également chargé dans les tests
Conclusion

Bien que je n'aie pas trouvé la cause réelle du non-chargement du fichier de vidage par Laravel, j'ai trouvé une solution de contournement en modifiant le nom de la base de données juste à des fins de test au lieu de définir une toute nouvelle connexion SQL à des fins de test. Cela a résolu le problème et le fichier de vidage de la base de données est désormais chargé pendant les tests.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal