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


How to create a Model object in Yii PHPUnit test without a fixture?

我正在为Yii应用程序编写PHPUnit测试。我在这里阅读:

提示:夹具文件过多可能会增加测试时间戏剧性地因此,您应该只提供fixture文件对于那些在测试过程中内容可能发生变化的表。表用作查找不会更改,因此不需要夹具文件。

我确实有一个很大的固定装置(180张唱片,加载时间超过20秒),它只是用作查找。但是,我确实需要将它从关联数组轻松地转换为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');
    ....
}

另一个选项:
创建db迁移时,应将其应用于生产db和测试数据库。此外,还应使用测试数据填充测试表。

这种方法的好处:

  1. 您将只运行一次populate sql(不像fixture—每次调用测试)
  2. 您的测试将执行得很快,因为数据库将做好准备
  3. 当您提交需要在数据库中使用新数据进行新测试的新功能时-您创建了数据库迁移,它将只在中执行一次明确的方式

例如:

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

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

是的,可以实现您的愿望。
例如:我有品牌的型号,它们有自己的固定装置:

<?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 fixture看起来要好得多,为了避免增加测试时间,应该使用.init.php文件。。。