简单的嘲笑

介绍

PHPUnit 手册描述了这样的模拟 :

使用验证期望的测试 double 替换对象的实践,例如断言已调用方法,被称为模拟。

因此,不是存储代码,而是创建一个观察者,它不仅取代了需要沉默的代码,而且还观察到现实世界中会发生特定的活动。

建立

让我们从一个简单的记录器类开始,为了清楚起见,只需显示发送到参数中的文本(通常它会做一些对单元测试有问题的事情,比如更新数据库):

class Logger {
    public function log($text) {
        echo $text;
    }
}

现在,让我们创建一个 Application 类。它接受一个 Logger 对象作为 run 方法的参数, run 方法又调用 Logger 的 log 方法来捕获应用程序已启动的对象。

class Application {
  public function run(Logger $logger) {
    // some code that starts up the application

    // send out a log that the application has started
    $logger->log('Application has started');
  }
}

如果以下代码按写入方式执行:

$logger = new Logger();
$app = new Application();
$app->run($logger);

然后将根据 Logger 内部的 log 方法显示 Application has started 文本。 ****

使用模拟进行单元测试

Application 类单元测试不需要验证 Logger 日志方法中发生了什么,它只需要验证它是否被调用。

在 PHPUnit 测试中,创建一个观察者来替换 Logger 类。设置该观察器以确保仅使用参数值 Application has started 调用 log 方法一次。 **

然后,观察者被发送到 run 方法,该方法验证实际上只调用了一次 log 方法并且测试用例通过了,但是没有显示任何文本。

class ApplicationTest extends \PHPUnit_Framework_TestCase {

  public function testThatRunLogsApplicationStart() {

    // create the observer
    $mock = $this->createMock(Logger::class);
    $mock->expects($this->once())
        ->method('log')
        ->with('Application has started');
    
    // run the application with the observer which ensures the log method was called
    $app = new Application();
    $app->run($mock);
  
  }
}