Unit testing 集成测试中的CakePHP 3模拟方法

Unit testing 集成测试中的CakePHP 3模拟方法,unit-testing,integration-testing,cakephp-3.0,Unit Testing,Integration Testing,Cakephp 3.0,我目前正在使用集成测试用例来测试某些端点上的响应,但无法解决如何使用模拟方法来停止测试,也无法执行发送电子邮件之类的操作 我的测试方法与以下类似: public function testInviteUser() { $this->post('/invite-user', [ 'name' => 'Joe Bloggs', 'email' => 'joe@bloggs.com' ]); $this->assertR

我目前正在使用集成测试用例来测试某些端点上的响应,但无法解决如何使用模拟方法来停止测试,也无法执行发送电子邮件之类的操作

我的测试方法与以下类似:

public function testInviteUser() {
    $this->post('/invite-user', [
        'name' => 'Joe Bloggs',
        'email' => 'joe@bloggs.com'
    ]);

    $this->assertRedirect([
        'controller' => 'Users',
        'action' => 'index'
    ]);
}

UsersTable
类使用一个
Mailer
,它监听
afterSave
事件并发送电子邮件。是否可以使用模拟对象来解决此问题?我了解在其他地方进行单元测试时如何使用它们,但看不出文档中的示例如何与集成测试相匹配。

我没有找到一种方法来实现这一点,而是使用了以下解决方案

在tests
bootstrap.php
中定义了一个名为
TESTING
的常量,然后使用
Defined('TESTING')
确定是否应该发送电子邮件。不太理想,因为我相信这是可能的模拟方法,但嘿,问题没有得到爱

更新

这是可能的钩到的方法。这将允许您在运行测试之前将模拟模型附加到控制器

例如:


如果您将发送电子邮件的逻辑放在自己的功能中,您应该能够执行以下操作:

$model = $this->getMockForModel('Users');
$model->expects($this->once())
    ->method('sendEmail')
    ->will($this->returnCallback(function ($user) {
        $this->assertEquals(123, $user->id);
    }));

不幸的是,这在集成测试中不起作用,因为模型是控制器的成员。然而,我后来发现,在运行测试之前,可以使用
controllerSpy
方法将模拟模型附加到控制器。
$model = $this->getMockForModel('Users');
$model->expects($this->once())
    ->method('sendEmail')
    ->will($this->returnCallback(function ($user) {
        $this->assertEquals(123, $user->id);
    }));