Creating and dropping a table during test breaks RefreshDatabase trait

Posted 7 months ago by flyingL123

I've created a trait using in my Laravel 5.6 app. The trait is called Projectable. This trait is meant to be used by Eloquent models. In order to test the trait, I wanted to create a ProjectableStub model to use in the tests. However, since this is an Eloquent model, it requires a table.

I wanted to simply create and drop a table just for testing. However, when I do this, it seems like something breaks regarding the RefreshDatabase functionality. To demonstrate, I am simply running two tests, both of which try to create a Product model with id = 1. Since the RefreshDatabase trait is being used, this should work fine. And, in the example below, it does:

    <?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 = [];
    }

However, as soon as I uncomment the two lines so that the stubs table is created and dropped, I get a SQL error that a duplicate ID is being used:

    <?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 = [];
    }
  1. Tests\Feature\ProjectableTest::example_second_test Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'

Does anyone know why creating and dropping a table within the test is causing this issue? Is there a better way to go about this? Maybe some way to add a migration at runtime for this new table?

Please sign in or create an account to participate in this conversation.

Laracasts Mascot

Hi, Have We Met Yet?

Did you know that, in addition to the forum, Laracasts includes well over 1000 lessons on modern web development? All for the price of one lunch out per month.

Sign Me Up

Channels

Reply to

Use Markdown with GitHub-flavored code blocks.