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

时间:2016-01-26 11:20:38

标签: unit-testing integration-testing cakephp-3.0

我目前正在使用集成测试用例来测试某些端点上的响应,但无法确定如何使用模拟方法来停止测试以及发送电子邮件等事情。

我的测试方法类似于以下内容:

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

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

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

2 个答案:

答案 0 :(得分:1)

实际上没有运气找到一种方法,而是使用了以下解决方案。

在名为bootstrap.php的测试中TESTING定义一个常量,然后使用defined('TESTING')确定是否应该触发电子邮件。不太理想,因为我确信这可以通过模拟方法实现,但嘿,问题不是爱!

更新!

这可以通过挂钩controllerSpyIntegrationTestCase方法实现。这将允许您在运行测试之前将模拟模型附加到控制器。

一个例子:

/**
 * @return void
 */
public function controllerSpy($event, $controller = null)
{
    parent::controllerSpy($event, $controller);

    if ($this->_controller) {
        $usersMock = $this->getMockForModel('App\Model\Table\UsersTable', ['mailer'], [
            'alias' => 'UsersTable',
            'table' => 'users'
        ]);

        $mailerMock = $this
            ->getMockBuilder('App\Mailer\UsersMailer')
            ->setMethods(['send'])
            ->getMock();

        $usersMock
            ->method('mailer')
            ->will($this->returnValue($mailerMock));

        $this->_controller->Users = $usersMock;
    }
}

答案 1 :(得分:0)

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

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