Rumah  >  Soal Jawab  >  teks badan

Pindahkan pangkalan data untuk menguji skema Laravel

<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粉722409996P粉722409996390 hari yang lalu406

membalas semua(2)saya akan balas

  • P粉952365143

    P粉9523651432023-08-27 15:05:56

    Nampaknya semasa menguji adalah tidak mungkin untuk mengendalikan pangkalan data dalam memori menggunakan fail dump skema

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

    Boleh cuba ni

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

    Cuba sahaja sebagai pilihan terakhir Secara peribadi, adalah disyorkan untuk berhijrah dalam persekitaran ujian Jika anda menggunakan kaedah ini, anda juga harus menambah cek untuk migrasi dalam persekitaran ujian

    balas
    0
  • P粉821274260

    P粉8212742602023-08-27 12:58:12

    Saya akhirnya faham.

    Punca masalah

    Masalahnya ialah persekitaran ujian tidak disediakan dengan betul. Saya tidak menemui punca sebenar, tetapi saya menemui cara untuk menyediakan persekitaran ujian supaya fail dump ditemui dan dimuatkan.

    Bagaimana cara menjejak ralat

    Ini menerangkan langkah-langkah yang saya ambil untuk mencari penyelesaiannya.

    Dalam database.php Saya menyalin pangkalan data ujian dan bukannya pangkalan data biasa
    • Dalam database.php Saya mempunyai sambungan pangkalan data utama:
    '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'),
                    ]) : [],
                ],

    dan uji sambungan

    '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', ''),
                    ],
    • Saya akan testing连接数据复制到一个新的mysqlbersambung hanya untuk melihat sama ada saya mendapat hasil yang sama pada baris arahan
    • Jadi, fail sekarang kelihatan seperti ini
    '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', ''),
                    ],*/
    • Di konsol, saya berlari php artisan:migrate
    • Fail pembuangan pangkalan data ditemui dan dimuatkan
    • Jadi, dalam kes biasa fail dump ditemui, tetapi dalam kes ujian ia tidak ditemui
    • Selepas beberapa penyelidikan, saya menukar tetapan persekitaran ujian dalam phpunit.xml, saya akan menerangkannya sekarang
    Failphpunit.xml

    phpunit.xmlNampak begini (fail penuh tidak ditunjukkan di sini):

    <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>
    • Jadi, kita dapat melihat bahawa sambungan pangkalan data ujian ditakrifkan sebagai ujian unit
    • Di web saya mendapat nasihat untuk menyediakan jadual pangkalan data sahaja daripada menukar keseluruhan sambungan untuk ujian kerana cara itu lebih mudah
    • Saya mencuba sesuatu seperti ini, jadi phpunit.xml menjadi
    <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>
    • Saya mengalih keluar sambungan ujian daripada database.php中删除了测试连接,并从.env dan mengalih keluar pembolehubah usang yang berkaitan daripada fail .env
    • Ini membetulkan isu, kini fail dump turut dimuatkan dalam ujian
    Kesimpulan

    Walaupun saya tidak menemui punca sebenar Laravel tidak memuatkan fail dump, saya menemui jalan penyelesaian dengan menukar nama pangkalan data hanya untuk ujian dan bukannya menentukan sambungan SQL yang baharu sepenuhnya untuk tujuan ujian. Ini membetulkan isu dan kini fail dump pangkalan data dimuatkan semasa ujian.

    balas
    0
  • Batalbalas