Owerll1984's avatar

Seed method works only once in Test classes

Hello everybody!

I encounter a weird issue using Artisan commands (directly or indirectly) in the setUp method of my integration test classes. In order to get test data, I want to migrate and seed data in a test database before running my tests. To do so, I use the setUp method:

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

        $this->seed();
    }

I also use the RefreshDatabase trait in order to empty my database before each test.

The first test runs perfectly and works as expected. Then, all other tests fail because of a CommandNotFoundException thrown in $this->seed();. I tried to use the debugger to find out what happens and saw that only two commands are loaded during the second test execution: list and help.

I really don't understand what happens here. Am I missing something?

Here is an example test class which fails:

class TVShowAPITest extends TestCase
{
    use RefreshDatabase;

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

        $this->seed();
    }

    public function testGetAllUnauthenticated()
    {
        $response = $this->get('/api/tvshows');
        $response->assertStatus(200)->assertJson([
            'meta' => [
                'last_page' => 2,
                'to' => 25,
                'total' => 30
            ]
        ]);
    }

    public function testGetAllAuthenticatedAsSuperadmin()
    {
        $superAdmin = User::where('username', env('SUPERADMIN_USERNAME', 'superadmin'))->firstOrFail();
        Passport::actingAs($superAdmin);
        $responseWhisp = $this->get('/api/tvshows');
        $responseWhisp->assertStatus(200)->assertJson([
            'meta' => [
                'last_page' => 6,
                'to' => 25,
                'total' => 120
            ]
        ]);
    }
}

Thanks in advance for your help!

0 likes
3 replies
bobbybouwmann's avatar

That's very odd indeed. It should work as expected here.

Have you tried seeding a specific class instead of everything that is in your seeder?

You can also try running the seed in the test itself, instead of the setUp method, but that goes against the purpose of seeding of course.

Keep in mind when using RefreshDatabase that it will only refresh the database on the first test. After that it will use a database transaction to revert everything.

2 likes
Owerll1984's avatar

Thanks for your answer.

As you suggested, I tried to seed a specific class. I also tried to run the seed method in my tests instead of the setUp method, without success.

In order to be sure the issue does not come from the tests themselves, I emptied all my test method bodies and then tried again. I removed RefreshDatabase too.

I also updated Laravel from version 6.X.X to 7.X.X.

The only way I found to get it work is by calling the command using shell_exec, but it is not a satisfying solution. I'm really running out of ideas.

Owerll1984's avatar

Hello!

No one has an idea? I am still stuck with this issue, unfortunately.

Please or to participate in this conversation.