CakePHP3:集成测试中的模拟方法?

时间:2018-10-02 11:11:13

标签: testing cakephp cakephp-3.0

我是单元/集成测试的新手,我想对控制器进行集成测试,它看起来像这样简化:

// ItemsController.php
public function edit() {

    // some edited item
    $itemEntity

    // some keywords
    $keywordEntities = [keyword1, keyword2, ...]

    // save item entity
    if (!$this->Items->save($itemEntity)) {
        // do some error handling
    }

    // add/replace item's keywords 
    if (!$this->Items->Keywords->replaceLinks($itemEntity, $keywordEntities)) {
       // do some error handling
    }
}

我有模型 Items Keywords ,其中Items areToMany关键字。我想测试控制器的错误处理部分。因此,我必须模拟 save() replaceLinks()方法,它们将返回false。

我的集成测试如下:

// ItemsControllerTest.php
public function testEdit() {

    // mock save method
    $model = $this->getMockForModel('Items', ['save']);
    $model->expects($this->any())->method('save')->will($this->returnValue(false));

    // call the edit method of the controller and do some assertions...

}

这对于save()方法工作正常。但是它不适用于replaceLinks()方法。显然是因为它不是模型的一部分。

我也尝试过这样的事情:

$method = $this->getMockBuilder(BelongsToMany::class)
    ->setConstructorArgs([
        'Keywords', [
            'foreignKey' => 'item_id',
            'targetForeignKey' => 'keyword_id',
            'joinTable' => 'items_keywords'
        ]
    ])
    ->setMethods(['replaceLinks'])
    ->getMock();

$method->expects($this->any())->method('replaceLinks')->will($this->returnValue(false));

但这也不起作用。是否有任何模拟 replaceLinks()方法的提示?

1 个答案:

答案 0 :(得分:1)

进行控制器测试时,我通常会尝试尽可能少地模拟,如果要在控制器中测试错误处理,我个人会尝试触发实际错误,例如通过提供未通过应用程序/验证规则的数据。如果这是一个可行的选择,那么您可能想尝试一下。

话虽如此,模拟关联的方法应如示例所示那样工作,但是您还需要用模拟替换实际的关联对象,因为与模型不同,关联没有全局注册表,其中可以放置模拟对象(getMockForModel()会为您做这些事情),以便您的应用程序代码无需进一步干预即可使用它们。

应该执行以下操作:

$KeywordsAssociationMock = $this
    ->getMockBuilder(BelongsToMany::class) /* ... */;

$associations = $this
    ->getTableLocator()
    ->get('Items')
    ->associations();

$associations->add('Keywords', $KeywordsAssociationMock);

这将修改表注册表中的Items表对象,并用替换实际的add()关联(关联集合的Keywords的作用就像是setter,即它会覆盖)。嘲笑一个。如果将它与模拟Items一起使用,则必须确保预先创建Items模拟,否则否则上例中检索的表将不会被模拟!