How to Run Laravel Database Seeder from PHPUnit Test setUp?
Asked Answered
W

6

35

I am trying to recreate the database before each test in some PHPUnit test cases. I am using Laravel 5.3. Here is TestCase:

class CourseTypesTest extends TestCase
{
    public function setUp()
    {
        parent::setUp();
        Artisan::call('migrate');
        Artisan::call('db:seed', ['--class' => 'TestDatabaseSeeder ', '--database' => 'testing']);
    }

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function test_list_course_types()
    {
        $httpRequest = $this->json('GET', '/api/course-types');
        $httpRequest->assertResponseOk();
        $httpRequest->seeJson();

    }

    public function tearDown()
    {
        Artisan::call('migrate:reset');
        parent::tearDown();
    }
}

Running phpunit fails with error:

$ phpunit PHPUnit 5.7.5 by Sebastian Bergmann and contributors.

E 1 / 1 (100%)

Time: 2.19 seconds, Memory: 12.00MB

There was 1 error:

1) CourseTypesTest::test_list_course_types ReflectionException: Class TestDatabaseSeeder does not exist

D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:749 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:644 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:709 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:74 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:63 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:2292 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Database\Console\Seeds\SeedCommand.php:64 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Container\Container.php:508 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Command.php:169 D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Command\Command.php:254 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Command.php:155 D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:821 D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:187 D:\www\learn-laravel\my-folder-api\vendor\symfony\console\Application.php:118 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Console\Application.php:107 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:218 D:\www\learn-laravel\my-folder-api\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:237 D:\www\learn-laravel\my-folder-api\tests\rest\CourseTypesTest.php:17

ERRORS! Tests: 1, Assertions: 0, Errors: 1.

but this class exists:
TestDatabaseSeeder inside database/seeds

Wald answered 22/1, 2017 at 12:14 Comment(0)
D
13

The problem is empty space in your --class argument. If you take close look at array '--class' => 'TestDatabaseSeeder ' there is space in the end ... this is the problem. Change it to '--class' => 'TestDatabaseSeeder' and it should work fine.

Deepfry answered 22/1, 2017 at 12:43 Comment(2)
Congrat! Empty space .. great :)Wald
If you like migrate only one time your data, check this #21894198Vibrio
J
38

Since version 5.8 you can do:

// Run the DatabaseSeeder...
$this->seed();

// Run a single seeder...
$this->seed(OrderStatusesTableSeeder::class);

Take a look at the documentation

Jerry answered 26/10, 2019 at 17:21 Comment(1)
How to run multiple seeder? Just multiple single call or I can pass an array to $this->seed()?Wafer
T
22

The DatabaseSeeder can be instantiated on its own, and its call method is public.

All you need to do in your CourseTypesTest class would be

(new DatabaseSeeder())->call(TestDatabaseSeeder::class);

Or you can make use of Laravel's app helper as follow

app(DatabaseSeeder::class)->call(TestDatabaseSeeder::class);
Tacheometer answered 12/10, 2018 at 16:20 Comment(0)
D
13

The problem is empty space in your --class argument. If you take close look at array '--class' => 'TestDatabaseSeeder ' there is space in the end ... this is the problem. Change it to '--class' => 'TestDatabaseSeeder' and it should work fine.

Deepfry answered 22/1, 2017 at 12:43 Comment(2)
Congrat! Empty space .. great :)Wald
If you like migrate only one time your data, check this #21894198Vibrio
L
0

Refresh your database with Artisan:

Artisan::call('migrate:fresh --seed');

This command removes your tables, creates the tables again (runs the migrations) and then seeds the tables with clean data.

Lucero answered 31/3 at 11:21 Comment(0)
A
0

For those stumbling on this question recently and are using a newer version of Laravel, ever since Laravel 8.0 there is a simpler way to do this.

If you use the Framework's provided base test case Illuminate\Foundation\Testing\TestCase and you use any of the db traits, such as Illuminate\Foundation\Testing\RefreshDatabase, you can just add a protected $seed = true; property to your tests and it will seed the db when doing the migrations.

Example from the documentation:

<?php
 
namespace Tests;
 
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
 
abstract class TestCase extends BaseTestCase
{
    use RefreshDatabase;

    /**
     * Indicates whether the default seeder should run before each test.
     *
     * @var bool
     */
    protected $seed = true;
}
Arriaga answered 17/6 at 5:25 Comment(0)
P
-3

enter image description here

You can try this way. You can execute this command when you run your test.

Pish answered 7/7, 2022 at 3:28 Comment(1)
Please include the source code in the answer body instead of using an image.Coprophilia

© 2022 - 2024 — McMap. All rights reserved.