I am using laravel 5 with php unit to create a laravel package. I have a Repository
..
namespace Myname\Myapp\Repositories;
use Myname\Myapp\Models\PersonModel;
class PersonRepository
{
protected $personModel;
public function __construct(PersonModel $personModel)
{
$this->personModel = $personModel;
}
public function testFunction($var)
{
return $this->personModel->find($var);
}
}
..which implements a Model
.
namespace Myname\Myapp\Models;
use Illuminate\Database\Eloquent\Model;
class PersonModel extends Model
{
protected $table = 'person';
}
Laravels IoC automatically injects PersonModel
into the constructor of PersonRepository
.
I am writing a unit test where I want to mock the PersonModel
model using mockery so I am not hitting the database during testing.
namespace Myname\Myapptests\unit;
use Mockery;
class PersonRepositoryTest extends \Myname\Myapptests\TestCase
{
/**
* @test
*/
public function it_returns_the_test_find()
{
$mock = Mockery::mock('Myname\Myapp\Models\PersonModel')
->shouldReceive('find')
->with('var');
$this->app->instance('Myname\Myapp\Models\PersonModel', $mock);
$repo = $this->app->make('Myname\Myapp\Repositories\PersonRepository');
$result = $repo->testFunction('var');
$this->assert...
}
}
When I run the test I get an error
1) Myname\Myapptests\unit\PersonRepositoryTest::it_returns_the_test_find ErrorException: Argument 1 passed to Myname\Myapp\Repositories\PersonRepository::__construct() must be an instance of Myname\Myapp\Models\PersonModel, instance of Mockery\CompositeExpectation given
From what I have read, mockery extends the class it is mocking so there should be no issue injecting the extended class in place of the type hinted parent (PersonModel)
Obviously I am missing something. Other examples explicitly inject the mocked object into the class they are then testing. Laravels IoC is (should be) doing this for me. Do I have to bind anything?
I have a feeling though that the mockery object isn't being created in the way I think (extending PersonModel) otherwise I assume I wouldn't see this error.
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');