如何在 Laravel 5.5 中使用 SQLite 内存数据库运行单元测试

3

我创建了一个测试数据库:

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
    }
}

在测试运行时,似乎数据库已经通过trait迁移,但未进行填充,因此没有返回任何内容。然而,文档并没有说明(或者我没有找到)如何在测试时填充数据库。它说明了如何通过运行“php artisan db:seed”手动填充,但在测试中显然不起作用,因为测试后数据库不存在了。我也不能在测试之前手动运行它,因为数据库还不存在。此外,这会使测试变得不切实际。
一些示例说明在测试的设置方法中运行填充,例如:
public function setUp() {
    Artisan::call('db:seed');
}

但是包括这个声明会导致错误:

RuntimeException:未设置Facade根。 (位于/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:218)

或者可以这样运行:

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

导致:

错误:在/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php:18中调用空值成员函数call()

我该如何实现这个?有没有任何完全可行的示例呢?到目前为止,我还没有找到任何 :(


我在我的测试中使用 https://github.com/orchestral/testbench-core,它基本上简化了事情,但它仅用于包测试,不确定它能提供多少帮助。 - Nikola Gavric
谢谢建议,但我想用框架本身来完成。 - steros
1个回答

1
你需要在setUp方法中调用$this->seed();。但是你需要确保在调用父类的setUp方法之前调用它,否则它会失败。
<?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
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接