使用 `Mockery::on()` 进行复杂参数匹配
当我们需要为预期的 方法调用 进行更复杂的 参数匹配 时,\Mockery::on() 匹配器非常方便。它接受一个 闭包 作为参数,当方法被调用时,该闭包会接收传递给该方法的参数。如果闭包返回 true,Mockery 将认为该参数已通过期望。如果闭包返回 false 或一个 “虚值”,则期望将不通过。
当我们需要为预期的 方法调用 进行更复杂的 参数匹配 时,\Mockery::on() 匹配器非常方便。它接受一个 闭包 作为参数,当方法被调用时,该闭包会接收传递给该方法的参数。如果闭包返回 true,Mockery 将认为该参数已通过期望。如果闭包返回 false 或一个 “虚值”,则期望将不通过。
\Mockery::on() 匹配器可用于各种场景——例如,根据多个键和值验证数组参数,或进行复杂的字符串匹配。
假设我们有以下代码。它没有做太多事情;只是通过将数据库中的 published 标志设置为 1 并将 published_at 设置为当前日期和时间来发布一个帖子。
<?php
namespace Service;
class Post
{
public function __construct($model)
{
$this->model = $model;
}
public function publishPost($id)
{
$saveData = [
'post_id' => $id,
'published' => 1,
'published_at' => gmdate('Y-m-d H:i:s'),
];
$this->model->save($saveData);
}
}
在测试中,我们将模拟模型,并为 save() 方法的调用设置一些期望:
<?php
$postId = 42;
$modelMock = \Mockery::mock('Model');
$modelMock->shouldReceive('save')
->once()
->with(\Mockery::on(function ($argument) use ($postId) {
$postIdIsSet = isset($argument['post_id']) && $argument['post_id'] === $postId;
$publishedFlagIsSet = isset($argument['published']) && $argument['published'] === 1;
$publishedAtIsSet = isset($argument['published_at']);
return $postIdIsSet && $publishedFlagIsSet && $publishedAtIsSet;
}));
$service = new \Service\Post($modelMock);
$service->publishPost($postId);
\Mockery::close();
这个示例中重要的部分是我们传递给 \Mockery::on() 匹配器的闭包。$argument 实际上是当 save() 方法被调用时所获得的 $saveData 参数。我们在此参数中检查几件事:
- 帖子 ID 已设置,并且与我们传递给
publishPost()方法的帖子 ID 相同。 published标志已设置,并且是1。published_at键存在。
如果这些要求中的任何一个不满足,闭包将返回 false,方法调用期望将不满足,Mockery 将抛出 NoMatchingExpectationException。
本菜谱条目改编自 Robert Basic 在其博客上发表的题为 Mockery 中的复杂参数匹配 的博文。