在 Laravel 测试期间创建和删除表

fly*_*123 2 php phpunit laravel

我在 Laravel 5.6 应用程序中使用了一个特征。该特征称为Projectable. 此特征旨在由 Eloquent 模型使用。为了测试该特征,我想创建一个ProjectableStub用于测试的模型。然而,由于这是一个 Eloquent 模型,因此它需要一个表。

我想简单地创建并删除一个表以进行测试。然而,当我这样做时,功能似乎出现了一些问题RefreshDatabase。为了演示,我只是运行两个测试,这两个Product测试都尝试使用id = 1. 由于RefreshDatabase正在使用该特征,因此这应该可以正常工作。并且,在下面的示例中,它确实:

<?php

namespace Tests\Feature;

use App\Product;
use Tests\TestCase;
use App\Concerns\Projectable;
use Illuminate\Support\Facades\Schema;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Database\Eloquent\Model as Eloquent;

class ProjectableTest extends TestCase
{
    use RefreshDatabase;

    public function setUp()
    {
        parent::setUp();

        //$this->createStubTable();
    }

    /**
     * @test
     */
    public function example_first_test()
    {
        factory(Product::class)->create(['id' => 1]);
    }

    /**
     * @test
     */
    public function example_second_test()
    {
        factory(Product::class)->create(['id' => 1]);
    }

    public function tearDown()
    {
        //$this->dropStubTable();

        parent::tearDown();
    }

    private function createStubTable()
    {
        Schema::create('stubs', function ($table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

    private function dropStubTable()
    {
        Schema::dropIfExists('stubs');
    }
}

class ProjectableStub extends Eloquent
{
    use Projectable;

    protected $table = 'stubs';

    protected $guarded = [];
}
Run Code Online (Sandbox Code Playgroud)

然而,一旦我取消注释这两行以便stubs创建并删除表,我就会收到一条 SQL 错误,指出正在使用重复的 ID:

<?php

namespace Tests\Feature;

use App\Product;
use Tests\TestCase;
use App\Concerns\Projectable;
use Illuminate\Support\Facades\Schema;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Database\Eloquent\Model as Eloquent;

class ProjectableTest extends TestCase
{
    use RefreshDatabase;

    public function setUp()
    {
        parent::setUp();

        $this->createStubTable();
    }

    /**
     * @test
     */
    public function example_first_test()
    {
        factory(Product::class)->create(['id' => 1]);
    }

    /**
     * @test
     */
    public function example_second_test()
    {
        factory(Product::class)->create(['id' => 1]);
    }

    public function tearDown()
    {
        $this->dropStubTable();

        parent::tearDown();
    }

    private function createStubTable()
    {
        Schema::create('stubs', function ($table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

    private function dropStubTable()
    {
        Schema::dropIfExists('stubs');
    }
}

class ProjectableStub extends Eloquent
{
    use Projectable;

    protected $table = 'stubs';

    protected $guarded = [];
}
Run Code Online (Sandbox Code Playgroud)

1) Tests\Feature\ProjectableTest::example_second_test Illuminate\Database\QueryException: SQLSTATE[23000]: 违反完整性约束: 1062 键“PRIMARY”的重复条目“1”

有谁知道为什么在测试中创建和删除表会导致此问题?有更好的方法来解决这个问题吗?也许有某种方法可以在运行时为这个新表添加迁移?

fly*_*123 6

我想这可能就是答案:

https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

创建表会导致自动RefreshDatabase提交创建的活动事务。

将存根表临时化就可以了。这也意味着我也不需要删除表,因为它会自动发生:

Schema::create('stubs', function ($table) {
    $table->temporary();
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});
Run Code Online (Sandbox Code Playgroud)

到目前为止似乎运行良好。