3

I setup a test database:

phpunit.xml:

<phpunit>
    <!... other stuff ...>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_CONNECTION" value="sqlite_testing"/>
    </php>
</phpunit>

database.php:

'connections' => [
    'sqlite_testing' => [
        'driver' => 'sqlite',
        'database' => ':memory:',
        'prefix' => '',
    ],

DatabaseSeeder.php

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            MyTableSeeder::class
        ]);
    }
}

MyTableSeeder.php:

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use App\My\Model;

class MyTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('model')->insert([
            'id' => 1,
            'created_at' => \Carbon\Carbon::now(),
            'updated_at' => \Carbon\Carbon::now()
        ]);

        /**
         * create random data
         */
        factory(Model::class, 50)->create();
    }
}

ModelFactory.php:

<?php

use Faker\Generator as Faker;

$factory->define(\App\My\Model::class, function (Faker $faker) {
    return [
        'id' => $faker->unique()->randomNumber(),
        'created_at' => $faker->dateTime('now'),
        'updated_at' => $faker->dateTime('now')
    ];
});

MyTest.php:

<?php

namespace Tests\Unit;

use App\My\Model;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class MyTest extends TestCase
{
    use RefreshDatabase;

    public function testGettingModel() {
        var_dump(Model::all()); // <-- returns a collection without any items

        $model = Model::where('id', 1)->first();

        $this->assertEquals('1', $model->id); // <-- trying to get property of non-object
    }
}

So at the test run it seems the database is migrated by the trait but not seeded and thus nothing is returned. The documentation does not state however (or I couldn't find it) how to seed the database upon testing. It states how to manually seed by running "php artisan db:seed" but that's not working in a test obviously as the database doesn't exist anymore after the test. And I can't run it manually as the database doesn't exist before the test. Also that would make testing impractical.

Some examples state running the seeding before testing in the setup method of the test like so:

public function setUp() {
    Artisan::call('db:seed');
}

But including this statement leads to the error:

RuntimeException : A facade root has not been set. (in /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:218)

Alternatively running it like so:

public function setUp()
{
    $this->artisan('db:seed');
}

Leads to:

Error : Call to a member function call() on null (in /vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php:18)

How do I actually do this? Is there any fully working example anywhere? So far I couldn't find any :(

steros
  • 1,794
  • 2
  • 26
  • 60
  • I use https://github.com/orchestral/testbench-core for my tests, it basically simplifies things, but it is used for package testing, not sure how much it can help out – Nikola Gavric Feb 19 '18 at 10:12
  • Thanks for the suggestion but I'd like to do it with the framework itself. – steros Feb 19 '18 at 11:14

1 Answers1

1

You have to call $this->seed(); in the setUp method. But you need to ensure to call the parents setUp method before or it will fail.

<?php

namespace Tests\Unit;

use App\My\Model;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class MyTest extends TestCase
{
    use RefreshDatabase;

    public function setUp()
    {
        parent::setUp();
        $this->seed();
    }

    public function testGettingModel() {
        $model = Model::where('id', 1)->first();
        $this->assertEquals('1', $model->id); // will assert to true if the id actually exists
    }
}
steros
  • 1,794
  • 2
  • 26
  • 60