遷移資料庫以測試Laravel的模式
P粉722409996
P粉722409996 2023-08-26 17:09:54
0
2
360

问题

  • 我正在使用 Laravel 8.83.23
  • 我有来自压缩迁移的模式转储文件,位于 database\schema\mysql-schema.dump
  • 测试运行在测试数据库上,就像在 database.php 中一样
'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', ''), ],
  • 在我压缩迁移之前,我的测试用例只使用了 DatabaseMigrations trait,并且测试数据库每次都会被重新创建,一切正常,以下是一个测试类的示例:
class SystemControllerTest extends TestCase { use WithFaker; use DatabaseMigrations; /** * @var User */ private $user; public function setUp(): void { parent::setUp(); //创建角色和数据 $this->seed(RoleAndPermissionSeeder::class); ... 等等
  • 迁移被找到并执行,重新创建了数据库
  • 然后,我压缩了迁移,所以所有的迁移都被删除了,我得到了 database\schema\mysql-schema.dump
  • php artisan migrate 通过命令行按预期工作,从转储文件中创建完整的数据库模式(它找到了它)
  • 然而,测试不再工作,因为出现了一个错误
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'cinema_test.roles' doesn't exist (SQL: delete from `roles`)
  • 当我在测试运行后检查 sql 测试数据库时,它是空的(只有表 migrations 被创建,而且是空的)
  • 即使在测试的设置中调用 artisan migrate,这个错误仍然存在:
public function setUp(): void { parent::setUp(); Artisan::call('migrate', array( '--database' => 'testing', '--force' => true)); //它在这里崩溃 $this->seed(RoleAndPermissionSeeder::class);
  • RoleAndPermissionSeeder 只操作不存在的 sql 表,因此出现错误
  • 我甚至尝试了 DatabaseMigrationsDatabaseTransactionsRefreshDatabase traits,但都没有成功
  • 我如何填充数据库数据?我无法读取 Artisan::call('migrate') 命令的输出,所以我不知道那里发生了什么
  • Artisan::call('migrate') 的返回代码是 0
  • 我是否可能遗漏了一些设置?

P粉722409996
P粉722409996

全部回覆 (2)
P粉952365143

看起來在測試時無法使用模式轉儲檔案來操作記憶體資料庫

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

#可以嘗試這樣做

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

只有在萬不得已的情況下才會嘗試,個人建議在測試環境中進行遷移,如果採用這種方法,還應添加測試環境遷移的檢查

    P粉821274260

    我終於弄清楚了。

    問題的原因

    問題出在測試環境的設定不正確。我沒有找到確切的原因,但我找到瞭如何設定測試環境以便找到並載入轉儲檔案。

    我如何追蹤錯誤

    這描述了我找到解決方法的步驟。

    database.php中,我複製了測試資料庫而不是正常的資料庫
    • database.php中,我有主資料庫連線:
    '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'), ]) : [], ],

    和測試連線

    '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', ''), ],
    • 我將testing連接資料複製到一個新的mysql連接中,只是為了看看在命令列上是否得到相同的結果
    • 所以,檔案現在看起來像這樣
    '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', ''), ],*/
    • 在控制台上,我運行了php artisan:migrate
    • 資料庫轉儲檔案被找到並載入
    • 因此,在正常情況下找到了轉儲文件,但在測試情況下沒有找到
    • 經過一些研究,我在phpunit.xml中更改了測試環境的設置,我現在將解釋它
    檔案phpunit.xml

    #phpunit.xml如下所示(此處未顯示完整文件):

         
    • 所以,我們可以看到測試資料庫連線定義為單元測試
    • 在網路上我找到了建議,只設定資料庫表,而不是為測試更改整個連接,因為這樣更容易
    • 我嘗試了這樣的方法,所以phpunit.xml變成了
         
    • 我從database.php中刪除了測試連接,並從.env檔案中刪除了相關的過時變數
    • 這修復了問題,現在轉儲檔案在測試中也被載入了
    結論

    雖然我沒有找到真正導致Laravel無法載入轉儲檔案的原因,但我找到了一個解決方法,即僅為測試更改資料庫名稱,而不是為測試目的定義全新的SQL連線。這解決了問題,現在在測試期間資料庫轉儲檔案會被載入。

      最新下載
      更多>
      網站特效
      網站源碼
      網站素材
      前端模板
      關於我們 免責聲明 Sitemap
      PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!