Lzh on GitHub

使用 `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 中的复杂参数匹配 的博文。