代码之家  ›  专栏  ›  技术社区  ›  steros

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

  •  3
  • steros  · 技术社区  · 6 年前

    我设置了一个测试数据库:

    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:尚未设置外观根目录。(in/vendor/laravel/framework/src/illighted/Support/Facades/Facade.php:218)

    或者像这样运行:

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

    导致:

    错误:调用null上的成员函数Call()

    我该怎么做呢?是否有任何完全可行的例子?到目前为止,我找不到任何:(

    1 回复  |  直到 6 年前
        1
  •  1
  •   steros    6 年前

    你必须打电话 $this->seed(); 在设置方法中。但您需要确保在之前调用parents 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
        }
    }