Migrate database to test Laravel's schema
P粉722409996
2023-08-26 17:09:54
<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>
Looks like you can't use a schema dump file to operate an in-memory database while testing
https://laravel.com/docs/9.x/migrations#squashing-migrations
You can try this
DB::unprepared(file_get_contents("path/file.sql"));
Only try it as a last resort. Personally, it is recommended to migrate in the test environment. If you adopt this method, you should also add a check for migration in the test environment
I finally figured it out.
Cause of the problem
The problem lies in the incorrect settings of the test environment. I didn't find the exact cause, but I found how to set up the test environment so that the dump file is found and loaded.
How do I track down errors
This describes the steps I took to find the solution.
In
database.php
I copied the test database instead of the normal databasedatabase.php
I have the main database connection:and test connection
testing
connection data into a newmysql
connection just to see if I got the same results on the command linephp artisan:migrate
phpunit.xml
, I will explain it nowFile
phpunit.xml
phpunit.xml
looks like this (the complete file is not shown here):phpunit.xml
becamedatabase.php
and removed the related obsolete variables from the.env
filein conclusion
While I didn't find the actual cause of Laravel failing to load the dump file, I found a workaround by changing the database name just for testing instead of defining a completely new SQL connection for testing purposes. This fixed the issue and now the database dump file is loaded during testing.