如何在没有夹具的情况下在Yii PHPUnit测试中创建Model对象?

时间:2015-06-25 08:06:40

标签: php object yii phpunit fixtures

我正在为我的Yii应用程序编写PHPUnit测试。我看了here

  

提示:拥有太多夹具文件会增加测试时间   大幅提升。因此,您应该只提供夹具文件   对于那些内容可能在测试期间发生变化的表。表   用作查找不会改变,因此不需要夹具文件。

我确实有一个大型灯具(180条记录,加载时间> 20秒),仅用作查找。但是,我确实需要将它从关联数组轻松转换为Model对象,就像您通常可以使用下面的fixture语法一样。该提示表明,还有一种方法可以在不使用夹具的情况下创建Model对象,但是没有提及 这是如何完成的。任何人都可以帮忙吗?

使用fixture创建Model对象:

// tests/fixtures/Order.php
return array(
    'row_id' => array(
        'id' => 1,
        'name' => 'hello',
    )
)

// tests/unit/AbcTest.php
public $fixtures = array(
    'orders' => 'Order',
)

public test_abc()
{
    $order = $this->orders('row_id');
    ....
}

2 个答案:

答案 0 :(得分:3)

另一种选择:
当您创建数据库迁移时,您应该将其应用于生产数据库和测试数据库,此外您应该使用测试数据填充测试表

这种方法的好处:

  1. 你只会运行一次填充sql(不喜欢 夹具 - 每次调用测试)。
  2. 您的测试将快速执行,因为db将会准备好。
  3. 当您提交需要使用db中的新数据进行新测试的新功能时 - 您创建数据库迁移,它将只执行一次 明确的方式。
  4. 例如:

    <?php
    
    class m150608_110143_init extends CDbMigration
    {
        public function safeUp()
        {
            $sql1 = "
                CREATE TABLE brand (
                    id INT AUTO_INCREMENT,
                    name VARCHAR(100) NOT NULL DEFAULT '',
                    country VARCHAR(50) NOT NULL DEFAULT '',
                    PRIMARY KEY (id)
                );
            ";
            $sql2 = "
                INSERT INTO brand VALUES
                    (null, 'aston martin', 'UK'),
                    (null, 'audi', 'Germany'),
                    (null, 'bmw', 'Germany'),
                    (null, 'citroen', 'France'),
                    (null, 'peugeot', 'France'),
                    (null, 'porsche', 'Germany'),
                    (null, 'toyota', 'Japan'),
                    (null, 'ferrari', 'Italy')
                ;
            ";
            // Production db.
            $this->setDbConnection(Yii::app()->db);
            $this->execute($sql1);
            // Test db.
            $this->setDbConnection(Yii::app()->dbUnitTest);
            $this->execute($sql1);
            // Populate test db with fixtures.
            $this->execute($sql2);
            return true;
        }
    
        public function down()
        {
            $sql = 'DROP TABLE brand;';
            // Test db.
            $this->setDbConnection(Yii::app()->dbUnitTest);
            $this->execute($sql);
            // Production db.
            $this->setDbConnection(Yii::app()->db);
            $this->execute($sql);
            return true;
        }
    }
    

    在测试中,你不必考虑固定装置。

答案 1 :(得分:1)

是的,可以达到你想要的效果。
例如:我的模型品牌有自己的夹具:

<?php
// protected/tests/fixtures/brand.php

return [
    1 => [
        'name' => 'Lexus',
        'country' => 'JPN',
    ],
    2 => [
        'name' => 'Acura',
        'country' => 'JPNE',
    ],
];

我有下一个代码:

    $brand = new Brand;
    $allBrands = $brand->findAll();

此代码将返回包含2个 CActiveRecord 对象的数组。而我们需要的一切 - 它只是用2个CActiveRecord对象构建相同的数组:

public function testGetAllAvailableBrands()
{
    // Get brands from fixture.
    $brand = new Brand;
    $allBrandsFromFixture = $brand->findAll();
    // Generate brands.
    $lexus = new Brand;
    $lexus->scenario = 'update';
    $lexus->name = 'Lexus';
    $lexus->country = 'JPN';
    $lexus->id = 1;
    $lexus->setPrimaryKey(1);
    $lexus->setIsNewRecord(false);
    $allBrandsGeneratedAtRuntime[] = $lexus;
    $acura = new Brand;
    $acura->scenario = 'update';
    $acura->name = 'Acura';
    $acura->country = 'JPNE';
    $acura->id = 2;
    $acura->setPrimaryKey(2);
    $acura->setIsNewRecord(false);
    $allBrandsGeneratedAtRuntime[] = $acura;
    // Brands from fixture should be equals to generated brands.
    $this->assertEquals($allBrandsFromFixture, $allBrandsGeneratedAtRuntime);
}

此测试将为绿色,因为我们的品牌完全相同。你试试这样的事情。

但我认为本机yii灯具看起来好多了,为避免增加测试时间,你应该使用 .init.php 文件...