Era*_*els 9 php mysql phpunit laravel
使用 php 8.0.2 和 Laravel 8.37.0,我正在运行测试,其中每个测试都应该刷新数据库数据,因为每个测试都有冲突的数据(由于唯一的约束)。
将内存数据库与 SQLite 一起使用,这是可行的,但是当我切换到 MySQL (v8.0.23) 时,我收到下一个错误:
1) Tests\Feature\Controllers\AuthControllerTest::testSuccessLogin
PDOException: There is no active transaction
Run Code Online (Sandbox Code Playgroud)
并且此后的测试由于数据已插入且测试后未清除而失败。
我想做的测试是:
<?php
namespace Tests\Feature\Controllers;
use App\Models\User;
use App\Models\User\Company;
use App\Repositories\UserRepository;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class AuthControllerTest extends TestCase
{
use RefreshDatabase;
protected array $connectionsToTransact = ['mysql'];
public function testSuccessLogin(): void
{
$this->artisan('migrate-data');
/** @var User $user */
$user = User::factory()->create([
'email' => 'test@website.com'
]);
$this->app->bind(UserRepository::class, function() use ($user) {
return new UserRepository($user, new Company());
});
$loginResponse = $this->post('/api/login', [
'email' => 'test@website.com',
'password' => 'password'
]);
$loginResponse->assertStatus(200);
$loginResponse->assertJsonStructure([
'data' => [
'user' => [
'name',
'surname',
'email',
'abilities'
],
'token',
]
]);
}
}
Run Code Online (Sandbox Code Playgroud)
执行此测试并检查数据库后,数据仍然存在。有和没有线protected array $connectionsToTransact = ['mysql'];给我相同的结果。
我的phpunit.xml文件看起来像:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
<report>
<html outputDirectory="reports/coverage"/>
</report>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="mysql"/>
<server name="DB_HOST" value="localhost"/>
<server name="DB_DATABASE" value="mysql_test"/>
<server name="DB_USERNAME" value="root"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
Run Code Online (Sandbox Code Playgroud)
这是一个已知的问题?或者我错过了什么?
Fra*_*ser 11
问题是您的测试包含隐式提交,因此结束了活动事务。
关于 -
“一旦我执行 CREATE 语句,我就会收到事务错误。” -
CREATE TABLE等是导致隐式提交的语句。
这反过来意味着该RefreshDatabase特征将不起作用,因为事务关闭时无法回滚。
因此PDOException: There is no active transaction
这似乎是 php 8.0 的一个已知问题/引发的错误 - https://github.com/laravel/framework/issues/35380
我根据我遇到的情况弄清楚了。我正在使用一个库,它使用迁移逻辑来执行数据迁移(因此$this->artisan('migrate-data');在我的代码中)。
使用该RefreshDatabase特征时,迁移会执行一次,然后启动事务。迁移逻辑对事务做了一些处理,我认为之后关闭它们,导致了我遇到的错误。
对我有用的解决方案是在开始事务之前覆盖RefreshDatabase特征以执行数据迁移:
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
trait RefreshDatabaseWithData
{
use RefreshDatabase;
protected function refreshTestDatabase(): void
{
if (! RefreshDatabaseState::$migrated) {
$this->artisan('migrate:fresh', $this->migrateFreshUsing());
$this->artisan('migrate-data'); // << I added this line
$this->app[Kernel::class]->setArtisan(null);
RefreshDatabaseState::$migrated = true;
}
$this->beginDatabaseTransaction();
}
}
Run Code Online (Sandbox Code Playgroud)
这仅在 Laravel 9 中进行了测试,但我不明白为什么这在以前的版本上不起作用。
| 归档时间: |
|
| 查看次数: |
16827 次 |
| 最近记录: |