Mockery and Laravel constructor injection

馋奶兔 提交于 2019-12-05 10:20:22
Fabio Antunes

Problem is when you create your mock:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel')
    ->shouldReceive('find')
    ->with('var');

So this:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel')
var_dump($mock);
die();

Will output something like this: Mockery_0_Myname_Myapp_Models_PersonModel

But this:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel')
    ->shouldReceive('find')
    ->with('var');
var_dump($mock);
die();

Will output this: Mockery\CompositeExpectation

So try doing something like this:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel');
$mock->shouldReceive('find')->with('var');

$this->app->instance('Myname\Myapp\Models\PersonModel', $mock);
$repo = $this->app->make('Myname\Myapp\Repositories\PersonRepository');
$result = $repo->testFunction('var');

While Fabio gives a great answer, the issue here is really the test setup. Mockery's mock objects do comply to contracts and will pass instanceof tests and type hints in method arguments.

The problem with the original code is that the chain of methods being called end up returning an expectation rather than a mock. We should instead create a mock first, then add expectations to that mock.

To fix it, change this:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel')
    ->shouldReceive('find')
    ->with('var');

Into this:

$mock = Mockery::mock('Myname\Myapp\Models\PersonModel');
$mock->shouldReceive('find')->with('var');

The variable $mock will now implement PersonModel.

Bonus:

Instead of 'Myname\Myapp\Models\PersonModel', use PersonModel::class. This is a lot more IDE-friendly and will help you when refactoring code later on.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!