Laravel + Mockery InvalidCountException

时间:2018-11-18 12:41:49

标签: laravel mockery

我正在尝试模拟a class,以防止其不得不调用第三方api。但是在设置模拟时,它似乎并不会影响控制器的动作。我确实尝试通过手动创建$this->postJson()-和Request类的实例来替换OEmbedControllercreate()方法正在被调用,但是我从Mockery收到了一个错误消息,那就是不是。

我在这里做什么错了?

错误:

  

Mockery \ Exception \ InvalidCountException:来自Mockery_2_Embed_Embed的方法create()应该精确调用1次,但必须调用0次。

测试:

class OEmbedTest extends TestCase
{
    public function tearDown()
    {
        Mockery::close();
    }

    /**
     * It can return an OEmbed object
     * @test
     */
    public function it_can_return_an_o_embed_object()
    {
        $url = 'https://www.youtube.com/watch?v=9hUIxyE2Ns8';

        Mockery::mock(Embed::class)
            ->shouldReceive('create')
            ->with($url)
            ->once();

        $response = $this->postJson(route('oembed', ['url' => $url]));
        $response->assertSuccessful();
    }
}

控制器:

public function __invoke(Request $request)
{
    $info = Embed::create($request->url);

    $providers = $info->getProviders();

    $oembed = $providers['oembed'];

    return response()
        ->json($oembed
            ->getBag()
            ->getAll());
}

2 个答案:

答案 0 :(得分:1)

似乎您在错误地嘲笑Embed类。如果您使用Laravel门面方法shouldReceive()而不是创建类本身的Mock,则该框架会将模拟放到您的服务容器中:

Embed::shouldReceive('create')
    ->with($url)
    ->once();

代替

Mockery::mock(Embed::class)
    ->shouldReceive('create')
    ->with($url)
    ->once();

还请注意,如果您测试的代码传递给模拟的参数与您通过with($url)学到的模拟有所不同,则模拟会认为自己未被调用。但是无论如何,调用未定义的方法都会收到另一个错误。

答案 1 :(得分:0)

我可以通过在测试中使用它来解决此问题:

protected function setUp()
{
    parent::setUp();

    app()->instance(Embed::class, new FakeEmbed);
}

然后像这样解决它

$embed = resolve(Embed::class);
$embed = $embed->create($url);