如何测试广播驱动程序?

How to test broadcast driver?

我想知道是否可以在 Laravel 中测试 ShouldBroadcast? 我的测试将触发实现 ShouldBroadcast 的 even,但是,我注意到广播没有发生。

当然,广播事件在它自己的应用程序中运行。

有人试过这样的测试吗?

这是一个老问题,但以防万一它可以帮助别人:我为自己做了一个断言函数,你应该添加到你的TestCase.php。

思路是设置广播驱动为"log"然后读取倒数第4行看是否是广播日志

在你的phpunit.xml

将以下行添加到节点:

<env name="BROADCAST_DRIVER" value="log"/>

在您的 TestCase.php 文件中

添加以下功能:

public function assertEventIsBroadcasted($eventClassName, $channel=""){
  $logfileFullpath = storage_path("logs/laravel.log");
  $logfile = explode("\n", file_get_contents($logfileFullpath));

  if(count($logfile) > 4){
    $supposedLastEventLogged = $logfile[count($logfile)-5];

    $this->assertContains("Broadcasting [", $supposedLastEventLogged, "No broadcast were found.\n");

    $this->assertContains("Broadcasting [".$eventClassName."]", $supposedLastEventLogged, "A broadcast was found, but not for the classname '".$eventClassName."'.\n");

    if($channel != "")
      $this->assertContains("Broadcasting [".$eventClassName."] on channels [".$channel."]", $supposedLastEventLogged, "The expected broadcast (".$eventClassName.") event was found, but not on the expected channel '".$channel."'.\n");
  }else{
    $this->fail("No informations found in the file log '".$logfileFullpath."'.");
  }
}

使用动态获取上次事件索引的 Adrienc 解决方案

private function getIndexOfLoggedEvent(array $logfile)
{
    for ($i = count($logfile) - 1; $i >=0 ; $i--) {
        if (strpos($logfile[$i], 'Broadcasting [Illuminate\Notifications\Events\BroadcastNotificationCreated]') !== false) {
            return $i;
        }
    }
}

这将为您提供上次广播的行索引

我把前面的两个答案都放在一起了。

这适用于 laravel 5.7。

在您的 TestCase.php 文件中:

public function assertEventIsBroadcasted($eventClassName, $channel = '')
{
    $date = Carbon::now()->format('Y-m-d');
    $logfileFullpath = storage_path("logs/laravel-{$date}.log");
    $logfile = explode("\n", file_get_contents($logfileFullpath));
    $indexOfLoggedEvent = $this->getIndexOfLoggedEvent($logfile);

    if ($indexOfLoggedEvent) {
        $supposedLastEventLogged = $logfile[$indexOfLoggedEvent];
        $this->assertContains('Broadcasting [', $supposedLastEventLogged, "No broadcast were found.\n");

        $this->assertContains(
            'Broadcasting [' . $eventClassName . ']',
            $supposedLastEventLogged,
            "A broadcast was found, but not for the classname '" . $eventClassName . "'.\n"
        );

        if ($channel != '') {
            $this->assertContains(
                'Broadcasting [' . $eventClassName . '] on channels [' . $channel . ']',
                $supposedLastEventLogged,
                'The expected broadcast (' . $eventClassName . ") event was found, but not on the expected channel '" . $channel . "'.\n"
            );
        }
    } else {
        $this->fail("No informations found in the file log '" . $logfileFullpath . "'.");
    }
}

private function getIndexOfLoggedEvent(array $logfile)
{
    for ($i = count($logfile) - 1; $i >= 0; $i--) {
        if (strpos($logfile[$i], 'local.INFO: Broadcasting') !== false) {
            return $i;
        }
    }
    return false;
}

测试可能如下所示:

/**
 * @test
 */
public function notifications_are_broadcasted()
{
    $notification = factory(Notification::class)->create();
    broadcast(new NewNotification($notification));
    $this->assertEventIsBroadcasted(
        NewNotificationEvent::class,
        'private-notification.' . $notification->id
    );
}

您可以使用断言 'expectsEvents',而不是检查日志中写入的内容,您可以测试某个事件是否已启动。

public function testMethod(){
   $this->expectsEvents(YourEventClass::class)
    ...your code test...
}

更多信息: https://laravel-guide.readthedocs.io/en/latest/mocking/