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