madprabh's avatar

Refresh database after every pest test

Hey Folks,

Here is my code for a PEST test and I want the database to refresh after every test but the below code doesn't work and gives me integrity constraint when running the seeder. Anyone know why? I am new to testing.

<?php
use App\Models\User;
use App\Models\Survey;
//use App\Database\Seeders\LanguageSeeder;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('can store survey responses when validation rules pass', function() {
	
	$user = User::factory()->withPersonalTeam()->unverified()->create();
	//seed the database with languages
	//seed the database with survey question types
	//seed the database with a survey with two questions
	Artisan::call('db:seed', [
        '--class' => 'LanguageSeeder',
    ]);
	Artisan::call('db:seed', [
        '--class' => 'QuestionTypeSeeder',
    ]);
	Artisan::call('db:seed', [
        '--class' => 'SurveySeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'SurveyLanguagesSeeder',
    ]);
    
    Artisan::call('db:seed', [
        '--class' => 'SurveyDetailSeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'SurveyPagesSeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'SurveyQuestionsSeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'SurveyPageQuestionsSeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'QuestionOptionsSeeder',
    ]);
    Artisan::call('db:seed', [
        '--class' => 'QuestionOptionLanguagesSeeder',
    ]);

    $response = $this->get(route('surveys.show', Survey::latest()->first()->global_id));
    $response->assertStatus(200);

});

it('cannot store survey responses when mandatory question validation fails', function() {


    $response = $this->get(route('surveys.show', Survey::latest()->first()->global_id));
    $response->assertStatus(200);

});

0 likes
3 replies
LaryAI's avatar
Level 58

To ensure that your database is refreshed after every test in Pest, you should use the RefreshDatabase trait correctly. This trait will automatically handle the database transactions and rollbacks for you, ensuring a clean state for each test.

However, using Artisan::call('db:seed') within your tests can sometimes lead to issues, especially with integrity constraints, because the database might not be in the expected state when the seeders are run.

Instead, you should use the DatabaseSeeder class to seed your database. This way, you can control the order and dependencies of your seeders more effectively.

Here's a revised version of your test code:

<?php

use App\Models\User;
use App\Models\Survey;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function () {
    // Seed the database before each test
    $this->artisan('db:seed', [
        '--class' => 'DatabaseSeeder',
    ]);
});

it('can store survey responses when validation rules pass', function() {
    $user = User::factory()->withPersonalTeam()->unverified()->create();

    $response = $this->get(route('surveys.show', Survey::latest()->first()->global_id));
    $response->assertStatus(200);
});

it('cannot store survey responses when mandatory question validation fails', function() {
    $response = $this->get(route('surveys.show', Survey::latest()->first()->global_id));
    $response->assertStatus(200);
});

In this example, the beforeEach function is used to seed the database before each test. This ensures that the database is in the correct state for each test without having to call Artisan::call('db:seed') multiple times within the test itself.

Make sure your DatabaseSeeder class includes all the necessary seeders:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call([
            LanguageSeeder::class,
            QuestionTypeSeeder::class,
            SurveySeeder::class,
            SurveyLanguagesSeeder::class,
            SurveyDetailSeeder::class,
            SurveyPagesSeeder::class,
            SurveyQuestionsSeeder::class,
            SurveyPageQuestionsSeeder::class,
            QuestionOptionsSeeder::class,
            QuestionOptionLanguagesSeeder::class,
        ]);
    }
}

This approach ensures that your database is properly seeded and refreshed for each test, avoiding integrity constraint issues.

MohamedTammam's avatar

Maybe you have a problem with your seeders that cause the constraint violation.

madprabh's avatar

The problem is the database doesn't refresh after each test. This causes the seeder to throw an integrity constraint because records already exists

1 like

Please or to participate in this conversation.