testing - CakePHP3 : Mock methods in integration tests?

标签 testing cakephp cakephp-3.0

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

// 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
    }
}

我有模型ItemsKeywords,其中Items 属于ToMany Keywords。我想测试 Controller 的错误处理部分。所以我必须模拟 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() 方法有什么提示吗?

最佳答案

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

也就是说,模拟关联的方法应该按照您的示例中所示的方式工作,但您还需要用您的模拟替换实际的关联对象,因为与模型不同,关联没有全局注册表,其中可以放置模拟(这就是 getMockForModel() 将为您做的)以便您的应用程序代码无需进一步干预即可使用它们。

应该这样做:

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

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

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

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

关于testing - CakePHP3 : Mock methods in integration tests?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52607172/

相关文章:

testing - 守夜人测试 : . sendKeys 和 .keys 不发送按键点击

django - 通过使用查询集传递请求来测试 login_view

php - 获取无效状态行 10380HTTP/1.1 200 OK

mysql - 在 CakePHP 3.x 中,我如何计算 MySql 表中的行数?

php - phpMyAdmin 和 CakePHP 3 中的结果不同

mysql - 在 CakePHP 3 中编辑主键

javascript - 为什么 Node.js Assert 没有 notOk() 方法?

python - 即使使用这个非常简单的 "test",为什么 python 比 Ruby 慢?

mysql - cakephp 从排序且有限的行加入

php - 混淆在 cakephp 中编写查询