Php 使用Queue::fake()测试侦听器

Php 使用Queue::fake()测试侦听器,php,laravel,unit-testing,mocking,Php,Laravel,Unit Testing,Mocking,我的Laravel 5.5应用程序有一个产品型号。产品模型有一个dispatchesEvents属性,如下所示: /** * The event map for the model. * * @var array */ protected $dispatchesEvents = [ 'created' => ProductCreated::class, 'updated' => ProductUpdated::class, 'deleted' =>

我的Laravel 5.5应用程序有一个
产品
型号。
产品
模型有一个
dispatchesEvents
属性,如下所示:

/**
 * The event map for the model.
 *
 * @var array
 */
protected $dispatchesEvents = [
    'created' => ProductCreated::class,
    'updated' => ProductUpdated::class,
    'deleted' => ProductDeleted::class
];
Queue::assertPushed(CallQueuedListener::class, function ($job) {
    return $job->class == CreateProductInMagento::class;
});
我还有一个名为
CreateProductInMagento
的侦听器,它映射到
EventServiceProvider
中的
ProductCreated
事件。此侦听器实现
ShouldQueue
接口

创建产品时,将触发
ProductCreated
事件,并将
CreateProductInMagento
侦听器推送到队列并运行

我现在正试图为所有这些编写一个测试。以下是我所拥有的:

/** @test */
public function a_created_product_is_pushed_to_the_queue_so_it_can_be_added_to_magento()
{
    Queue::fake();

    factory(Product::class)->create();

    Queue::assertPushed(CreateProductInMagento::class);
}
但是我得到一个
预期的[App\Listeners\Magento\Product\CreateProductInMagento]作业没有被推送。
错误消息


如何使用Laravel的
Queue::fake()
方法测试可排队侦听器?

运行
artisan Queue:work
无法解决此问题,因为在测试时,Laravel配置为使用
sync
驱动程序,该驱动程序仅在测试中同步运行作业。我不确定为什么这项工作没有被推进,尽管我猜这与Laravel在测试中以不同的方式处理事件有关。无论如何,有一种更好的方法可以用来编写测试,既可以解决问题,又可以使代码更具可扩展性

在您的
ProductTest
中,您不应该测试
创建的产品是否被推送到队列中,从而可以添加到magento
,而应该测试是否触发了事件。您的
ProductTest
不关心
ProductCreated
事件是什么;这是
ProductCreatedTest
的工作。因此,您可以使用来稍微更改您的测试:

/** @test */
public function product_created_event_is_fired_upon_creation()
{
    Event::fake();

    factory(Product::class)->create();

    Event::assertDispatched(ProductCreated::class);
}
然后,创建一个新的
ProductCreatedTest
来单元测试您的
ProductCreated
事件。这是您应该放置作业被推送到队列的断言的位置:

/** @test */
public function create_product_in_magento_job_is_pushed()
{
    Queue::fake();

    // Code to create/handle event.

    Queue::assertPushed(CreateProductInMagento::class);
}

这还有一个额外的好处,那就是使您的代码在将来更容易更改,因为您的测试现在更接近于只测试他们负责的类的实践。此外,它还应该解决您遇到的问题,即从模型触发的事件没有排队等待您的作业

这里的问题是侦听器不是推送到队列的作业。相反,有一个
illumb\Events\CallQueuedListener
作业已排队,并在解析时依次调用相应的侦听器

所以你可以这样做你的断言:

/**
 * The event map for the model.
 *
 * @var array
 */
protected $dispatchesEvents = [
    'created' => ProductCreated::class,
    'updated' => ProductUpdated::class,
    'deleted' => ProductDeleted::class
];
Queue::assertPushed(CallQueuedListener::class, function ($job) {
    return $job->class == CreateProductInMagento::class;
});

尝试
php artisan queue:work
我启动了您提到的命令,然后尝试运行测试。同样的错误。谢谢你的反馈。我添加了行
事件(newproductcreated($product))
在第二个测试中,您有
//代码来创建/处理事件。
。该测试仍然失败,并显示相同的错误消息。我应该做些不同的事情吗?或者说我应该做些什么?这很有趣。我在队列方面做了很多工作,但在事件方面做得不多。当然,您同时注册了事件和侦听器?是的,下面是我的
EventServiceProvider
:是的,成功了。我的考试现在通过了。谢谢你的帮助。@alepeino这很有帮助。但是,我仍然无法在lravel文档中找到有关此的任何信息。你能分享一下这方面的相关链接吗。谢谢。