PHPUnit 集成
Mockery 被设计为一个易于使用的 独立 模拟对象框架,因此它与任何测试框架的集成完全是可选的。要集成 Mockery,我们需要为测试定义一个 tearDown() 方法,其中包含以下内容(我们可以使用更短的 \Mockery 命名空间别名):
public function tearDown() {
\Mockery::close();
}
这个静态调用会清理当前测试使用的 Mockery 容器,并运行为我们的期望所需的任何验证任务。
为了在使用 Mockery 时更简洁,我们还可以显式地使用 Mockery 命名空间并使用一个更短的别名。例如:
use \Mockery as m;
class SimpleTest extends \PHPUnit\Framework\TestCase
{
public function testSimpleMock()
{
$mock = m::mock('simplemock');
$mock->shouldReceive('foo')->with(5, m::any())->once()->andReturn(10);
$this->assertEquals(10, $mock->foo(5));
}
public function tearDown()
{
m::close();
}
}
Mockery 附带了一个自动加载器,因此我们不需要在测试中散布 require_once() 调用。要使用它,请确保 Mockery 在我们的 include_path 中,并将以下内容添加到我们的测试套件的 Bootstrap.php 或 TestHelper.php 文件中:
require_once 'Mockery/Loader.php';
require_once 'Hamcrest/Hamcrest.php';
$loader = new \Mockery\Loader;
$loader->register();
如果我们使用 Composer,我们可以将其简化为包含 Composer 生成的自动加载文件:
require __DIR__ . '/../vendor/autoload.php'; // 假设 vendor 在上一级目录
Hamcrest.php 文件名有一个小写 “h”(即 hamcrest.php)。如果将 Hamcrest 升级到 1.0.0,请记住检查所有项目的文件名是否已更新。要将 Mockery 集成到 PHPUnit 中并避免必须调用 close 方法,以及让 Mockery 将自己从代码覆盖率报告中移除,请让您的测试用例扩展 \Mockery\Adapter\Phpunit\MockeryTestCase:
class MyTest extends \Mockery\Adapter\Phpunit\MockeryTestCase
{
}
另一种方法是使用提供的 trait:
class MyTest extends \PHPUnit\Framework\TestCase
{
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
}
扩展 MockeryTestCase 或使用 MockeryPHPUnitIntegration trait 是 推荐的 将 Mockery 与 PHPUnit 集成的方式,自 Mockery 1.0.0 以来。
PHPUnit 监听器
在 1.0.0 版本之前,Mockery 提供了一个 PHPUnit 监听器,它会在测试结束时为我们调用 Mockery::close()。自 1.0.0 版本以来,这发生了重大变化。
现在,Mockery 提供了一个 PHPUnit 监听器,如果 Mockery::close() 没有被调用,它会使测试失败。它可以帮助识别我们忘记包含 trait 或扩展 MockeryTestCase 的测试。
如果我们使用 PHPUnit 的 XML 配置方法,我们可以包含以下内容来加载 TestListener:
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener"></listener>
</listeners>
请确保 Composer 或 Mockery 的自动加载器存在于引导文件中,否则我们还需要定义一个指向 TestListener 类文件的 “file” 属性。
如果我们以编程方式创建测试套件,我们可以像这样添加监听器:
// 创建套件。
$suite = new PHPUnit\Framework\TestSuite();
// 创建监听器并将其添加到套件中。
$result = new PHPUnit\Framework\TestResult();
$result->addListener(new \Mockery\Adapter\Phpunit\TestListener());
// 运行测试。
$suite->run($result);
Mockery::close() 方法验证模拟的期望,并提供一个 PHPUnit 监听器,它会在每次测试后自动为我们调用此方法。然而,当使用 PHPUnit 的进程隔离时,此监听器不会在正确的进程中被调用,导致期望可能得不到满足,但不会引发任何 Mockery\Exception。为了避免这种情况,我们不能依赖提供的 Mockery PHPUnit TestListener,并且我们需要显式地调用 Mockery::close。最简单的解决方案是像前面解释的那样,将此调用包含在 tearDown() 方法中。