如何解决mysql DB 上的 PDOException:并行测试时“已经存在活动事务” 说明:
- Laravel 版本:8.33.1
- PHP 版本:8.0.3
- 数据库驱动程序和版本:MySQL 5.7.32
说明:
您好,我们想测试多个数据库交互,所以我们需要独立的测试和一种方法来创建/迁移/种子我们的 mysql 数据库(磁盘存储)副本。我们正在使用 Sanctum 进行身份验证。
我一直在尝试使用新的并行测试功能并阅读您的不同文档和相关问题。
我的结论是:
- 需要 DatabaseTransactions 特性,其他特性全部或部分被 ParallelTesting“替换”
- 新的 ParallelTesting::setUpTestDatabase() 正是我在创建数据库时需要的内容
- 不需要测试数据库定义,因为 ParallelTesting 已经创建了 name_test_1、name_test_2 形式的副本
- 如果没有 --recreate-databases,则不会再次调用播种,因为它仅在创建其测试数据库后调用
我的种子是一堆工厂,DB::unprepared。
手动运行 art migrate:fresh
和 art db:seed
,然后在没有 art test
的情况下运行 --parallel
,测试工作正常。但是,当使用 --parallel --recreate-databases
运行时,播种不起作用,我偶然发现了这个错误:
PDOException: 已经有一个活动事务
EE 2 / 2 (100%)
Time: 00:14.187,Memory: 20.00 MB
There were 2 errors:
1) Tests\Feature\AuthTest::testAuthLogin
PDOException: There is already an active transaction
[root]/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:137
[root]/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:113
[root]/vendor/laravel/framework/src/Illuminate/Foundation/Testing/DatabaseTransactions.php:21
[root]/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:129
[root]/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:90
2) Tests\Feature\AuthTest::testAuthGetUser
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'company_id' cannot be null (SQL: insert into `users` (`company_id`,[cut]))
[root]/vendor/laravel/framework/src/Illuminate/Database/Connection.php:678
[root]/vendor/laravel/framework/src/Illuminate/Database/Connection.php:638
[root]/vendor/laravel/framework/src/Illuminate/Database/Connection.php:472
[root]/vendor/laravel/framework/src/Illuminate/Database/Connection.php:424
[root]/vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php:32
[root]/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2882
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:1547
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1052
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1017
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:858
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:275
[root]/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:234
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:278
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:236
[root]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:230
[root]/tests/Feature/AuthTest.php:73
FAILURES!
Tests: 2,Assertions: 0,Errors: 2.
提供者/AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\ParallelTesting;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
// Executed when a test database is created...
ParallelTesting::setUpTestDatabase(function () {
Artisan::call('db:seed');
});
}
}
测试/CreatesApplication.php
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
trait CreatesApplication
{
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
}
测试/TestCase.php
<?php
namespace Tests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use DatabaseTransactions;
use CreatesApplication;
}
迁移/*.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class ImportDbTables extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::unprepared(file_get_contents(base_path().'/database/dump.sql'));
}
}
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="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<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>
示例测试
<?php
namespace Tests\Feature;
use App\Models\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class AuthTest extends TestCase
{
public function testAuthLogin()
{
$user = User::factory()->create([
'email' => 'test@login.com','password' => 'test_1',]);
$response = $this->postJson('/auth/login',[
'email' => 'test@login.com','device_name' => 'test_1'
]);
$response->assertOk()->assertJsonFragment([
'status' => 'Success','message' => null
]);
$this->assertArrayHasKey('data',$response);
$this->assertArrayHasKey('token',$response['data']);
}
}
任何帮助将不胜感激!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。