Unit testing 解释Laravel 5.1关于注册事件处理程序和测试的问题;“期望值”;
[前言:我解决了我的根本问题,这个问题是为了理解它最初为什么会发生] 我一直在调试一个测试用例,其中我通过Unit testing 解释Laravel 5.1关于注册事件处理程序和测试的问题;“期望值”;,unit-testing,laravel,events,laravel-5.1,Unit Testing,Laravel,Events,Laravel 5.1,[前言:我解决了我的根本问题,这个问题是为了理解它最初为什么会发生] 我一直在调试一个测试用例,其中我通过$this->expectsEvents(App\Events\MyTestEvent::class)注册了一个事件预期。即使事件侦听器的代码已运行,测试仍不断给我以下错误: 异常:未触发以下事件: [应用程序\事件\ MyTestEvent] 通过大量的尝试和错误,当同时使用两种不同的注册事件处理程序的方法(在EventServiceProvider.php中)时,似乎出现了问题。请参见下
$this->expectsEvents(App\Events\MyTestEvent::class)
注册了一个事件预期。即使事件侦听器的代码已运行,测试仍不断给我以下错误:
异常:未触发以下事件:
[应用程序\事件\ MyTestEvent]
通过大量的尝试和错误,当同时使用两种不同的注册事件处理程序的方法(在EventServiceProvider.php中)时,似乎出现了问题。请参见下面的案例1,这是我注册事件处理程序的原始代码。如果我将auth.login
处理程序移动到$listen
数组(请参见案例2),我的测试工作正常,问题就解决了
问题:
- 在案例1中,我是否做错了什么?或者
- 这是已知的/预期的行为吗?或者
- 这是Laravel事件处理程序中的错误吗
案例1(原始代码,MyTestEvent的expectsEvent()测试失败)
案例2(修改代码,MyTestEvent的expectsEvent()成功)
我认为问题在于你的测试预期的是一个不同的事件。您是否混淆了要测试的事件?这一行:
$this->expectsEvents(App\Events\MyTestEvent::class);
正在等待在App\Events\MyTestEvent
类中激发的事件。在案例1和案例2中与之关联的侦听器是App\Listeners\TestListener
。(从您提供的代码中不清楚是否曾经触发过MyTestEvent
,这可以解释您看到的异常。)
但是,您为其注册侦听器的事件是auth.login
。在案例1中,侦听器是一个匿名函数,在案例2中,侦听器由App\Listeners\LoginListener
类实例化。要对此进行测试,测试代码应如下所示:
$this->expectsEvents('auth.login');
假设触发了auth.login
事件,您不应该期望监听器代码在之后执行
我仍然觉得奇怪的是,在一种情况下,
MyTestEvent
似乎会触发,而在另一种情况下则不会,因为它似乎与您正在收听的事件都没有关系。也许在您的各种事件和侦听器类中发布代码会让事情变得更清楚。谢谢。我的测试应该激发+期望类的偶数MyTestEvent
。“auth.login”事件的注册似乎是测试行为的一部分。我不是在测试auth.login,它只是导致我出现问题的原因。在案例1中,expectsEvent
似乎无法正常工作,因为我的处理程序启动了,然后测试用例就好像从未看到过事件一样。我最好的猜测是,有什么东西让Laravel感到困惑,导致我的测试用例预期的MyTestEvent
没有正确注册。您是否尝试过使用传递到boot()
的$events
变量,而不是Event
facade?i、 例如,$events->listen('auth.login',…)
而不是Event::listen('auth.login',…)
文档中的示例就是这样做的,但我不确定为什么会有不同。绘图变厚:使用$events
而不是外观会导致一切按预期工作。我想知道为什么。另一个测试:当你使用facade时,你是否也有use-Event代码>在类定义之前的文件顶部?在早期版本的Laravel中,使用facade不需要做任何特殊的事情,但我在5.1中发现,必须通过use语句显式地让类知道您将使用facade。没有使用事件类顶部的code>将导致facade无法访问允许您访问已注册事件的基础DispatcherContract
。
$this->expectsEvents(App\Events\MyTestEvent::class);
$this->expectsEvents('auth.login');