使用现有的迁移表进行 laravel 单元测试

Posted

技术标签:

【中文标题】使用现有的迁移表进行 laravel 单元测试【英文标题】:Use existing migrations tables for laravel unit testing 【发布时间】:2016-01-27 08:02:43 【问题描述】:

我想使用一组现有的迁移来创建表,以便我将种子数据填充到其中。我正在使用Orchestra Testbench 进行测试。 Examples like this 显示动态创建表:

DB::schema()->create('oauth_identities', function($table) ...

但我想使用现有的迁移。

TestCase.php:

use Orchestra\Testbench\TestCase as OrchestraTestCase;

abstract class TestCase extends OrchestraTestCase

    protected function getBasePath()
    
        // reset base path to point to our package's src directory
        return __DIR__ . '/../vendor/orchestra/testbench/fixture';
    

DBTestCase.php:

类 DBTestCase 扩展了 TestCase 受保护的 $artisan;

/*
 * Bootstrap the application
 */
public function setUp()

    parent::setUp();

    $this->artisan = $this->app->make('Illuminate\Contracts\Console\Kernel');

    $this->artisan('migrate', [
            '--database' => 'testbench',
            '--realpath' => realpath(__DIR__.'/../database/migrations'),
        ]
    );



protected function getEnvironmentSetUp($app)

    parent::getEnvironmentSetUp($app);

    $app['config']->set('database.default', 'testbench');
    $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => ''
        ]
    );

UserTest.php:

class UserTest extends DBTestCase

    use DatabaseMigrations;

   private function seedUser()
   

       return [
           'email' => 'myemail',
            ...
       ];
       ...
   

...
public function testCreateUser()

    $user = User::create($this->seedUser());

    die(print_r($user)); 
    ...

错误:

在 \App\Tests\UserTest::testCreateUser 一般错误:1没有这样的表:用户

但在我的迁移中,我肯定会创建表:

Schema::create('users', function (Blueprint $table) ...

那么如何使用现有的迁移表并为迁移生成种子数据?


编辑:现在在 DBTestCase 中设置我的 DB 驱动程序 'driver' => 'sqlite', 后运行 phpunit 时,会引发错误:

在 .../Database/SQLiteConnection.php 中找不到类 'Doctrine\DBAL\Driver\PDOSqlite\Driver'

导航到SQLiteConnection.phpuse Doctrine\DBAL\Driver\PDOSqlite\Driver as DoctrineDriver; 中的PDOSqlite 以红色突出显示,表示它是一个未定义的命名空间。

我在我的 database.php 中有这个驱动程序:

数据库.php:

'default' => env('DB_CONNECTION', 'mysql'),

'connections' => [

    'sqlite' => [
        'driver'   => 'sqlite',
        'database' => storage_path('database.sqlite'),
        'prefix'   => '',
    ],

【问题讨论】:

【参考方案1】:

如果你使用的是 Laravel 5,你可以设置你的测试用例来使用这样的数据迁移:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase

    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    
        $this->visit('/')
             ->see('Laravel 5');
    

通过使用DatabaseMigration 特征,数据库在每个测试用例之前迁移并在它之后回滚。如果您尝试在不同的测试用例中测试相同的数据,请记住这一点。

【讨论】:

嗨蒂姆,谢谢。即使在使用 DatabaseMigrations Trait 之后,它也会抛出 Doctrine\DBAL\Driver\PDOSqlite\Driver not found in /Users/.../Database/SQLiteConnection.php 你是否在你的database.php中定义了一个测试连接? 缺少作曲家依赖:"doctrine/dbal": "~2.3"【参考方案2】:

假设您在包中正确设置了ServiceProvider,并且还在boot 方法中使用loadMigrationsFrom 指向了您的迁移文件,那么您只需要像这样更改您的测试类:

class TestCase extends \Orchestra\Testbench\TestCase

    public function setUp(): void
    
        parent::setUp();

        $this->artisan('migrate', ['--database' => 'testbench'])->run();
    

    /**
     * add the package provider
     *
     * @param $app
     * @return array
     */
    protected function getPackageProviders($app)
    
        return [\Vendor\Your-Packagename::class];
    


    /**
     * Define environment setup.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    protected function getEnvironmentSetUp($app)
    
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => '',
        ]);
    

【讨论】:

以上是关于使用现有的迁移表进行 laravel 单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何对 Django South“数据迁移”进行单元测试

为 Laravel 映射现有的数据库表

使用 Laravel Passport 范围进行单元测试

单元测试能否成功添加到现有的生产项目中?如果是这样,如何以及是不是值得?

Laravel 单元测试依赖注入

使用 PHPUnit 在 Laravel 控制器中进行单元测试 Guzzle