我正在使用 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);
}
为什么不将负载发送到
tickets
队列?我必须为测试明确分配一个队列名称。即->onQueue('tickets')
。如果它是故意忽略它,我在哪里可以找到对这种行为的引用?我最终追溯
dispatch()
以了解为什么 #1 是这样,但我只是发现它是类的一个奇怪的(参见 #3)实例化Illuminate\Foundation\Bus\PendingDispatch
如下所示:// 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
如何将负载插入队列?是基于事件的,魔法的,还是?new PendingDispatch(new static(...func_get_args()));
到底在做什么?具体来说,我不确定new static
作为构造函数的参数在做什么。PendingDispatch
的构造函数甚至不接受多个参数。
最佳答案
对于 #1,当单元测试时,您不使用实际的队列实现,而是使用 Laravel facades fake
方法(类似于 Mock)。 Event、Queue、Bus、Notification 等 Facade 都提供对 ::fake()
静态方法的访问,作为模拟应用程序实现的便利包装器。
如您所见,dispatch
帮助程序简单地包装了一个 PendingDispatch
实例。 Dispatchable
特征是它被定义的地方。队列通过序列化传递给它的类来工作,因此任何公开定义的属性都会自动在队列中可用。
new static
引用您推送到队列的作业类。基本上,使用传递给 dispatch
助手的所有参数创建一个新的 myself 实例。
使用 PHP,您不需要提供方法签名,您可以像这样定义一个方法:
public function myMethod()
并称它为
$obj->myMethod($a, $b, $c, $d)
这就是 func_get_args()
正在做的事情,它将所有参数传递给被调用的方法。这就是魔法。在上面的示例中,func_get_args()
将返回一个数组 [$a, $b, $c, $d]
。
关于Laravel:队列作业如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48632654/