测试

CodeIgniter 的构建是为了使测试的框架和应用程序尽可能简单。
PHPUnit 的支持是内置的,而且是 PHPUnit.xml 已经为你的应用程序设置好了。

它还提供了许多方便的助手方法,使测试你应用程序的方方面面尽可能简单。

测试你的应用

Test 类

为了利用提供的额外工具,你的 Test 类必须继承 \CIUnitTestCase:

class MyTests extends \CIUnitTestCase
{
    . . .
}

Services 模拟

你经常会发现,当模拟来自 services 的各种响应的时候,你需要模拟一个在 application/Config/Services.php 中定义的服务来限制你的测试所需的代码。 在测试控制器和其他集成测试时尤其如此。

在测试模式下,系统在 Service 类上加载一个包装器,它提供了两个新方法, injectMock()reset()

injectMock()

该方法允许你定义将由服务类返回的确切实例。 你可以用这个设置 Services 的属性,以便它以某种方式表现,或者用一个模拟的类替换服务。

public function testSomething()
{
    $curlrequest = $this->getMockBuilder('CodeIgniter\HTTP\CURLRequest')
                        ->setMethods(['request'])
                        ->getMock();
    Services::injectMock('curlrequest', $curlrequest);

    // Do normal testing here....
}
第一个参数是要替换的 service 。 名称必须与 Services 中的函数名相匹配。
第二个参数是替换它的实例。

reset()

删除 Services 类中的所有被模拟的类,并将其恢复到原来的状态。

测试数据库

测试类

为了利用 CodeIgniter 为测试提供的内置数据库工具,你的测试必须继承 \ CIDatabaseTestCase

class MyTests extends \CIDatabaseTestCase
{
    . . .
}

因为在 setUp()tearDown() 阶段中运行特殊的功能,所以必须确保存在。 如果你需要使用这些方法,你可以调用父方法,否则你将缺少很多这里描述的功能。

class MyTests extends \CIDatabaseTestCase
{
    public function setUp()
    {
        parent::setUp();

        // Do something here....
    }


    public function tearDown()
    {
        parent::tearDown();

        // Do something here....
    }
}

测试数据库设置

在运行数据库测试时,你需要提供一个可以在测试期间使用的数据库。 而不是 使用 PHPUnit 内置的数据库特性,框架提供了特定于 CodeIgniter 的工具。 第一个 第一步是确保你有一个 tests 数据库组设置在 application/Config/Database.php

它指定只在运行测试时使用的数据库连接,以保证其他数据的安全。

如果你的团队中有多个开发人员,那么你可能希望保留你的凭证存储 .env 。 为了做到这一点,编辑文件以确保下面的行是存在的,并拥有正确的信息:

database.tests.dbdriver = 'MySQLi';
database.tests.username = 'root';
database.tests.password = '';
database.tests.database = '';

Migrations 和 Seeds

在运行测试时,你需要确保数据库具有正确的模式设置。 每个测试都处于一个已知的状态。你可以使用 migrations 和 seeds 来设置数据库, 通过在测试中添加几个类属性。

class MyTests extends \CIDatabaseTestCase
{
    protected $refresh = true;
    protected $seed    = 'TestSeeder';
    protected $basePath = 'path/to/database/files';
}

$refresh

这个布尔值决定在每次测试之前是否完全刷新数据库。 如果是 true ,将所有迁移回滚到版本0,然后将数据库迁移到最新可用迁移。

$seed

如果存在且不为空, 则根据指定要使用的 Seed 文件的名称, 在每次运行测试之前都用测试数据填充数据库。

$basePath

默认情况下, CodeIgniter 会定位在 tests/_support/database/migrationstests/_support_database/seeds 测试期间应该运行的 migrations 和 seeds。
你可以通过指定 $basePath 路径来更改此目录。 这不应该包括 migrationsseeds 目录, 应该指向包含两个子目录的单个目录的路径。

辅助方法

CIDatabaseTestCase 类提供了一些辅助方法,以帮助你测试你的数据库。

seed($name)

允许你手动将 Seed 加载到数据库中。 唯一的参数是要运行的 seed 的名称。 seed 必须在 $basePath 指定的路径中存在。

dontSeeInDatabase($table, $criteria)

对当前行在数据库表中不存在 $criteria 中 (key/value) 键值对匹配作出断言。

$criteria = [
    'email' => 'joe@example.com',
    'active' => 1
];
$this->dontSeeInDatabase('users', $criteria);

seeInDatabase($table, $criteria)

对当前行在数据库表中存在 $criteria 中 (key/value) 键值对匹配作出断言。

$criteria = [
    'email' => 'joe@example.com',
    'active' => 1
];
$this->seeInDatabase('users', $criteria);

grabFromDatabase($table, $column, $criteria)

从列匹配 $criteria 的指定表中返回 $column 的值。如果不止一行被发现,它只会测试第一个。

$username = $this->grabFromDatabase('users', 'username', ['email' => 'joe@example.com']);

hasInDatabase($table, $data)

将新的一行数据插入到数据库中。 此行在当前测试运行后删除。 $data 是一个关联 将数据数组插入到表中。

$data = [
    'email' => 'joe@example.com',
    'name'  => 'Joe Cool'
];
$this->hasInDatabase('users', $data);

seeNumRecords($expected, $table, $criteria)

对 $criteria 数据和数据库表中数据行的数量作出断言。

$criteria = [
    'deleted' => 1
];
$this->seeNumRecords(2, 'users', $criteria);