Fixtures 是测试中非常重要的一部分。他们的主要目的是建立一个固定/已知的环境状态以确保 测试可重复并且按照预期方式运行。
你可以使用 Fixtures 来确保用户DB表包含固定的数据。 你在运行一个测试之前加载一个或者多个 fixture object,并在结束后卸载他们。
配置:
Yii2.0 高级模板的 Fixtures 默认路径是在 common\fixtures 下,路径的配置是在 console\config\main.php 中配置的。
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'common\fixtures',
],
],
编写Fixture类:
使用 Fixture,你需要创建一个新的 class 继承自 yii\test\Fixture 或者 yii\test\ActiveFixture 。前一个类对于一般用途的 Fixture 比较适合, 而后者则有一些增强功能专用于与数据库和 ActiveRecord 一起协作。
说明:
- Fixture 类的名称应该以
Fixture
字符作为后缀。 - yii\test\ActiveFixture 适用 SQL 数据库
- yii\mongodb\ActiveFixture 适用 Mongo DB
- yii\elasticsearch\ActiveFixture(从版本 2.0.2 开始)适用 Elasticsearch
- 可以使用 $tableName 或者 $modelClass 指定数据写入目标
- $dataFile 指定数据来源,如果未设置的话默认 FixturePath/data/TableName.php
- 如果未指定 $dataFile 数据来源,重载 getData() 方法也可以
- getData() 中 key user1,user2 为数据别名
- 你不需要特别的为自动增长(auto-incremental)的列指定数据, Yii 将会在 Fixture 被加载时自动的填充正确的列值到这些行中;或者你指定id值为固定值。
<?php
namespace common\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
// 先找 $tableName
public $tableName = 'user';
// 再找 modelClass
public $modelClass = 'common\models\User';
// 指定数据来源,如果未设置的话默认 __DIR__.'/data/user.php'
public $dataFile = __DIR__ . '/data/user_data.php';
// 如果未指定 $dataFile 也可以在此方法中返回写入表中的数据
public function getData()
{
return [
'user1' => [
'username' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
'user2' => [
'username' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
}
}
Fixture 依赖:
一个 Fixture 可能依赖于其他的 Fixtures ,通过它的 yii\test\Fixture::$depends 来指定。 当一个 Fixture 被加载前,它依赖的 Fixture 会被自动的加载;同样,当某个 Fixture 被卸载后, 它依赖的 Fixtures 也会被自动的卸载。
比如一个 UserProfileFixture
可能需要依赖于 UserFixture
, 因为 user profile 表包括一个指向 user 表的外键。那么, 这个依赖关系可以通过 yii\test\Fixture::$depends 属性来指定,比如如下:
namespace common\fixtures;
use yii\test\ActiveFixture;
class UserProfileFixture extends ActiveFixture
{
public $modelClass = 'common\models\UserProfile';
public $depends = ['common\fixtures\UserFixture'];
}
编写数据来源文件:
默认情况下,Fixture 类会在其所在的目录下面的 data
子目录寻找相关的数据文件,也可在 $dataFile 指定数据的来源。
如上例中 $dataFile 指定为当前目录下的data目录 下 user_data.php
<?php
return [
'user1' => [
'username' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
'user2' => [
'username' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
或者在数据库中填好数据,然后导出JSON文件,上传至Fixture的data目录下。
<?php
$json = file_get_contents(__DIR__.'/user.json');
$data = json_decode($json, true);
return $data['RECORDS'];
Fixture的使用:
Yii 通过 yii fixture
命令行工具来支持 fixtures 操作
加载 Fixtures
命令格式
yii fixture/load <fixture_name>
必需参数 fixture_name
指定一个将被加载数据的 Fixture 名字。 你可以同时加载多个 Fixtures 。 以下是这个命令的正确格式:
// 加载 `User` fixture
yii fixture/load User
// 与上面相同,因为 “fixture” 命令的默认动作是“加载”
yii fixture User
// 加载几个 fixtures
yii fixture User UserProfile
// 加载所有 fixtures
yii fixture/load "*"
// 与上面相同
yii fixture "*"
// 加载所有 fixtures 除了这些
yii fixture "*" -DoNotLoadThisOne
// 加载 fixtures, 但在不同的命名空间中搜索它们。默认命名空间是:common\fixtures。
yii fixture User --namespace='alias\my\custom\namespace'
// 加载全局 fixture `some\name\space\CustomFixture` 在加载其他 fixtures 之前.
// 默认情况下,此选项设置为 `InitDbFixture` 以禁用/启用完整性检查。您可以用用逗号分离来
// 指定几个全局 fixtures。
yii fixture User --globalFixtures='some\name\space\Custom'
卸载 Fixtures
运行如下命名去卸载 Fixtures:
// 卸载 User fixture,默认情况下它将清除 fixture 存储(例如“用户”表,或“用户”集合如果这是 mongodb fixture)。
yii fixture/unload User
// 卸载几个 fixtures
yii fixture/unload User,UserProfile
// 卸载所有 fixtures
yii fixture/unload "*"
// 卸载所有 fixtures 除了这些
yii fixture/unload "*" -DoNotUnloadThisOne
全局Fixtures配置:
Fixtures有一个默认全局配置 yii\test\InitDbFixture,全局配置格下如下:
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'myalias\some\custom\namespace',
'globalFixtures' => [
'some\name\space\Foo',
'other\name\space\Bar'
],
],
]
自动生成 Fixtures:
Yii 还可以为你自动生成一些基于一些模板的 Fixtures。 你能够以不同语言格式用不同的数据生成你的 Fixtures。 这些特征由 Faker 库和 yii2-faker
扩展完成。 关注 guide 扩展获取更多的文档。
总结:
在上面,我们描述了如何定义和使用 Fixture,在下面,我们将总结出一个 标准地运行与 DB 有关的单元测试的规范工作流程:
- 使用
yii migrate
工具来让你的测试数据库更新到最新的版本; - 运行一个测试:
- 卸载 yii fixture/unload 清空所有的相关表数据
- 加载 yii fixture/load 填充数据
- 执行真实的测试用例
- 卸载 yii fixture/unload 清空所有的相关表数据
- 重复步骤 2 直到所有的测试结束。