【问题标题】:How Do I Seed My Database in the setupBeforeClass Method in a Laravel 4 Unit Test?如何在 Laravel 4 单元测试的 setupBeforeClass 方法中播种我的数据库?
【发布时间】:2014-03-20 13:31:08
【问题描述】:

我有一个 Laravel 4 测试类,其中包含一些测试,我想在运行测试之前为我的数据库播种。使用 setup() 函数为每个测试重新设置种子需要很长时间。但是,当我尝试在静态 setupBeforeClass() 函数或构造函数中播种时,我显然不能使用 $this->seed() 方法。

但我也不能使用程序化 Artisan 命令,因为当我这样做时,我收到以下错误:PHP Fatal error: Class 'Artisan' not found in <test class name>.

这是我想用来播种的代码:

Artisan::call('migrate:refresh');
Artisan::call('db:seed', array('--class'=>'TestSeeder');

请告诉我如何在每个测试class而不是每个测试case

中为我的数据库播种一次

【问题讨论】:

    标签: database testing laravel-4


    【解决方案1】:

    我遇到了同样的问题,用这个解决了

    passthru('cd ' . __DIR__ . '/../.. & php artisan migrate:refresh & db:seed --class=TestSeeder');
    

    【讨论】:

    • 是的!你知道我搜索这样的答案多久了!
    • 这不能完全正常工作,因为测试通常是在内存中使用 sqlite。
    【解决方案2】:

    实现类似效果的“即兴”但非常干净的恕我直言的方法是在 setUp 中执行此操作,但只运行一次(类似于 setupBeforeClass 所做的)喜欢这个:

    use Illuminate\Support\Facades\Artisan;
    
    class ExampleTest extends TestCase {
    
        protected static $db_inited = false;
    
        protected static function initDB()
        {
            echo "\n---initDB---\n"; // proof it only runs once per test TestCase class
            Artisan::call('migrate');
            // ...more db init stuff, like seeding etc.
        }
    
        public function setUp()
        {
            parent::setUp();
    
            if (!static::$db_inited) {
                static::$db_inited = true;
                static::initDB();
            }
        }
    
        // ...tests go here...
    }
    

    ...这是我的解决方案,它看起来很简单并且工作正常,解决了在每次测试运行之前播种和重建数据库结构的性能问题。但请记住,“正确”的测试方法,让您最大程度地相信您的测试方法不会以隐藏错误的方式微妙地相互依赖,是在每次测试之前重新播种您的数据库方法,所以如果你能承受性能损失(对于我的测试用例,我买不起,但是 ymmv...),只需将种子代码放在简单的 setUp 中。

    【讨论】:

    • 所有测试完成后如何处理重置数据库?
    • 你可以使用DatabaseTransaction trait,然后db在每个测试方法之前都是一样的。
    • @melihovv 这将不起作用,因为数据库是在事务内部创建的。第一次测试后,数据库创建被撤消,静态属性阻止它被重新创建。
    【解决方案3】:

    这是迄今为止我找到的最佳解决方案

    class ExampleTest extends TestCase {
    /**
     * This method is called before
     * any test of TestCase class executed
     * @return void
     */
    public static function setUpBeforeClass()
    {
        parent::setUpBeforeClass();
        print "\nSETTING UP DATABASE\n";
        shell_exec('php artisan migrate --seed');
    }
    
    /**
     * This method is called after
     * all tests of TestCase class executed
     * @return void
     */
    public static function tearDownAfterClass()
    {
        shell_exec('php artisan migrate:reset');
        print "\nDESTROYED DATABASE\n";
        parent::tearDownAfterClass();
    }
    /** tests goes here **/ }
    

    【讨论】:

      【解决方案4】:

      你现在可以做:

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

      在您的 setUp() 方法中进行测试。

      seed() 方法接受种子类作为参数。

      public function seed($class = 'DatabaseSeeder')
      {
          $this->artisan('db:seed', ['--class' => $class]);
      
          return $this;
      }
      

      【讨论】:

        【解决方案5】:

        2022 年更新: 从新的 Laravel 版本开始,您可以使用:

        use RefreshDatabase;
        

        过时的:

        这个特性是重置数据库的好方法

        <?php
        namespace Tests;
        
        use Illuminate\Support\Facades\Artisan;
        
        trait MigrateFreshAndSeedOnce
        {
            /**
             * If true, setup has run at least once.
             * @var boolean
             */
            protected static $setUpHasRunOnce = false;
        
            /**
             * After the first run of setUp "migrate:fresh --seed"
             * @return void
             */
            public function setUp() : void
            {
                parent::setUp();
                if (!static::$setUpHasRunOnce) {
                    Artisan::call('migrate:fresh');
                    Artisan::call(
                        'db:seed',
                        ['--class' => 'CompleteTestDbSeeder'] //add your seed class
                    );
                    static::$setUpHasRunOnce = true;
                }
            }
        }
        

        【讨论】:

        • 来自此处的未署名副本:medium.com/helpspace/…
        • 它来自某个地方的 GitHub,但很高兴你在 medium 上找到了一篇文章。
        • 对我来说,第一个测试通过,第二个测试“一般错误:1 没有这样的表:用户”。所以数据库表不会在测试之间保留。
        • 不要用这个...只用use RefreshDatabase;...
        猜你喜欢
        • 1970-01-01
        • 2019-05-22
        • 2017-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-22
        • 2019-03-23
        • 2017-06-23
        相关资源
        最近更新 更多