【问题标题】:Laravel: how does a queue job work?Laravel:队列作业如何工作?
【发布时间】:2018-07-15 21:42:23
【问题描述】:

我正在使用 Larevel 5.5 的内置 Redis 队列。当我编写一个测试队列负载时,我注意到测试无法识别我在queue.php中分配的默认队列名称:

'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => 'tickets', 
    ]

我正在向队列中插入一个有效负载,如下所示:Job::dispacth($payload)。它在实际的非测试代码中按预期工作。

我的测试代码:

public function testTicketQueue()
{
    Queue::fake();
    $payload = ['this is a ticket'];
    TicketProcessor::dispatch($payload)
        ->onQueue('tickets') // Fails without this
        ;
    Queue::assertPushedOn('tickets', TicketProcessor::class);
}
  1. 为什么不将负载发送到tickets 队列?我必须为测试显式分配队列名称。即->onQueue('tickets')。如果它故意忽略它,我在哪里可以找到对这种行为的参考?

  2. 我最终回溯dispatch() 以了解#1 为何如此,但我才发现这是Illuminate\Foundation\Bus\PendingDispatch 类的一个奇怪的(参见#3)实例化,如下所示:

    // Illuminate\Foundation\Bus\Dispatchable
    public static function dispatch()
    {
        return new PendingDispatch(new static(...func_get_args()));
    }
    
    // Illuminate\Foundation\Bus\PendingDispatch
    public function __construct($job)
    {
        $this->job = $job;
    }
    

    dispatch 如何将有效负载插入队列?是基于事件的、魔术的还是?

  3. new PendingDispatch(new static(...func_get_args())); 到底在做什么?具体来说,我不确定new static 作为构造函数的参数做了什么。 PendingDispatch 的构造函数甚至不接受多个参数。

【问题讨论】:

  • 你用的是什么测试框架?
  • @btl Laravel 有自己的包装器,但它似乎在下面使用 PHPUnit。
  • 对,我没有看到 PHPUnit 标签,只是集成测试。我会为您发布一些信息。
  • 检查 phpunit.xml 以查看正在运行的 que 驱动程序。可能不是redis。

标签: laravel testing phpunit integration-testing laravel-5.5


【解决方案1】:

对于 #1,在单元测试时,您不使用实际的队列实现,而是使用 Laravel 外观 fake 方法(类似于 Mock)。事件、队列、总线、通知等门面都提供对::fake() 静态方法的访问,作为模拟应用程序实现的便利包装。

如您所见,dispatch 助手只是简单地包装了一个 PendingDispatch 实例。 Dispatchable 特征是它定义的地方。队列通过序列化传递给它的类来工作,因此任何公开定义的属性都会自动在队列中可用。

new static 正在引用您要推送到队列的作业的类。基本上,使用传递给 dispatch 助手的所有参数创建我自己的新实例。

使用 PHP,您不需要提供方法签名,您可以定义如下方法:

public function myMethod()

然后这样称呼它

$obj->myMethod($a, $b, $c, $d)

这就是func_get_args() 正在做的事情,它将所有参数传递给被调用的方法。这就是魔法。在上面的示例中,func_get_args() 将返回一个数组 [$a, $b, $c, $d]

【讨论】:

  • 1:用我的测试代码更新了我的帖子,它使用了官方文档中的fake。我不需要像Queue:fake() 之后那样的实际队列实现吗? assertPushedOn 否则失败,文档不清楚。
  • 2/3:我仍然不明白创建PendingDispatch 实例将有效负载插入队列的部分。我现在明白它使用new static 创建了一个PendingDispatch 和我的分配的job 属性。但是您实际序列化并将其插入队列的后续步骤在哪里?
猜你喜欢
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 2018-06-20
  • 2018-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多