php - mock 用 andReturn 返回新对象

标签 php unit-testing laravel mocking phpunit

我有以下方法:

public function getThreads()
{
    $results = \DB::select(\DB::raw(config('sql.messages.threads')), [$this->user->user_id]);

    $messagesThreadsModel = app()->make(MessagesThreadsModel::class);
    $messages = [];

    foreach ($results as $r) {
        $message = $messagesThreadsModel->find($r->messages_thread_id);
        $message->unread = $r->unread;
        $messages[] = $message;
    }

    return $messages;
}

为了测试上面的内容,我模拟了调用\DB::select(通过 Laravel 的外观)以返回对象列表,就像 DB 类通常所做的那样。然后我加载消息线程模型,它再次被模拟并替换在容器中(因此 app()->make() 将返回其模拟实例,而不是实际模型)。

最后是这个:

$messagesThreadsModel->find($r->messages_thread_id);

再次被模拟返回一个虚拟对象(一个 stub ?)。全部如下:

$threadsList = $this->mockThreads();

    // mock the raw expression, check the query 
    \DB::shouldReceive('raw')->once()->with(m::on(function($sql)
    {
        return strpos($sql, 'messages') !== false;
    }))->andReturn(true);

    // mock the DB call, return a list of objects
    \DB::shouldReceive('select')->once()->with(true, [$this->usersModel->user_id, $this->usersModel->user_id, $this->usersModel->user_id])->andReturn($threadsList);

    $mockThreadResult = new \StdClass;
    $mockThreadResult->last = "date";

    $this->messagesThreadModel->makePartial();

    // HERE IS THE TRICKY PART!
    $this->messagesThreadModel->shouldReceive('find')->times(count($threadsList))->andReturn($mockThreadResult);

    $this->app->instance('App\Freemiom\Models\Messages\MessagesThreads', $this->messagesThreadModel);

    $messages = new Messages($this->usersModel);
    $threadList = $messages->getThreads();

现在有什么问题?因为我传递了已经创建的虚拟对象,所以每次在循环中调用 ->find 方法时都会返回相同的对象。

我应该如何告诉 mockery 在每次调用时返回一个新对象?有可能吗?或者也许我应该进行一些代码重构以使其全部可测试?

最佳答案

因此,为了能够在每次连续调用同一个模拟方法时返回一个新对象,我必须像这样使用 andReturnUsing:

$this->messagesThreadModel->shouldReceive('find')->times(count($threadsList))->andReturnUsing(function()
{
    $mockThreadResult = new \StdClass;
    $mockThreadResult->last = "date";

    return $mockThreadResult;
});

这将模仿同样使用 find() 方法返回新对象的 Eloquent 模型的行为。

关于php - mock 用 andReturn 返回新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35866129/

相关文章:

c# - 与 ShouldBeEquivalentTo 相反

node.js - 如何在类中 stub 所需的模块?

php - Symfony4 sqlite3 连接

php - laravel 5 样板应用程序不工作

asp.net-mvc - 这个 TestMethod 有什么问题?

php - 使用表单数据上传 Ajax 文件 Laravel 5.3

php - Laravel 使用 PHP 链表实现 SplDoublyLinkedList();

php - 在另一个 Controller 中调用 Controller 功能

php - img src 不适用于 php 和 php 变量

php - 如何覆盖 html 元素但保留 block 的其余部分?