首页 > 解决方案 > Laravel 8 中的单元测试事件抛出 EventFake::__construct() 必须实现接口 Illuminate\Contracts\Events\Dispatcher,给定 null

问题描述

我正在尝试使用单元测试来伪造一个事件,所以没有数据库,没有应用程序,只有纯类。

我正在关注我当前版本 Laravel 8 的文档,但我仍然收到错误消息

1) Tests\Unit\HandShake\ConfirmApplicationHandShakeActionTest::BasedOnAnExistentAppIConfirmTheHandShake
TypeError: Argument 1 passed to Illuminate\Support\Testing\Fakes\EventFake::__construct() must implement interface Illuminate\Contracts\Events\Dispatcher, null given, called in /Users/pablo/Workspace/xxxx/vendor/laravel/framework/src/Illuminate/Support/Facades/Event.php on line 38

正如你所看到的,它要求一个实现接口 Dispatch 的对象,我的 Event 具有特征调度,但无论如何这里它说我正在传递null

我的测试代码如下

<?php

namespace Tests\Unit\HandShake;

use App\Actions\ConfirmApplicationHandShakeAction;
use App\Events\HandShakeReceivedEvent;
use App\Exceptions\NotFoundApplicationException;
use App\Models\Application;
use Illuminate\Support\Facades\Event;
use Mockery\MockInterface;
use Mockery;

use PHPUnit\Framework\TestCase;

class ConfirmApplicationHandShakeActionTest extends TestCase
{

    /**
     *
     * @test
     * @throws NotFoundApplicationException
     */
    public function BasedOnAnExistentAppIConfirmTheHandShake()
    {

        $appName = 'testDummy';

        Event::fake([HandShakeReceivedEvent::class]);

        $applicationModel = Mockery::mock(Application::class, function (MockInterface $mock) {
            $mock->shouldReceive('exists')
                ->andReturn(true)
                ->once();
        });
        $confirmation = new ConfirmApplicationHandShakeAction($applicationModel);
        $confirmation->execute($appName);

我正在测试的课程是

    <?php
declare(strict_types=1);

namespace App\Actions;

use App\Events\HandShakeReceivedEvent;

use App\Exceptions\NotFoundApplicationException;
use App\Models\Application;


/**
 * Class ConfirmApplicationHandShakeAction
 * @package App\Actions
 */
class ConfirmApplicationHandShakeAction
{
    /**
     * @var Application
     */
    private $application;

    /**
     * ConfirmApplicationHandShakeAction constructor.
     * @param Application $application
     */
    public function __construct(Application $application)
    {
        $this->application = $application;
    }

    /**
     * @param string $appName
     * @throws NotFoundApplicationException
     */
    public function execute(string $appName)
    {

        if ( ! $this->application->exists($appName)) {
            throw new NotFoundApplicationException('The Application do not exists or is not active');
        }

        HandShakeReceivedEvent::dispatch($appName);
    }
}

最后是活动

    <?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class HandShakeReceivedEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

可能是我错过了一个愚蠢的角色​​的那些时刻之一,但我遇到了这个错误,我找不到正确的解决方案。

更新

我一直在挖掘,我发现 getFacadeRoot() 返回 null,所以我假设某些东西没有正确初始化,仍然不知道

static::swap($fake = new EventFake(static::getFacadeRoot(), $eventsToFake));

如果您发现问题或可以指出正确的方向,请提前感谢您。我还尝试了 FakeFor 和 Fake 而不将事件作为参数发送

标签: laravel

解决方案


问题解决了

当您使用 artisan 创建测试文件时,由于某些原因,PHPUnit\Framework\TestCase他们使用的是 PHPUnit 中的那个,但他们应该使用 Laravel 中的那个Tests\TestCase

扩展您的测试Tests\TestCase 将解决问题


推荐阅读