Pregunta

I need to mock Laravel's Eloquent\Model with Mockery and it is kind of tricky because it uses static methods.

I solved this issue with the following code but I wonder if there is a better/smarter way to do this.

<?php

use Ekrembk\Repositories\EloquentPostRepository;

class EloquentPostRepositoryTest extends TestCase {
    public function __construct()
    {
        $this->mockEloquent = Mockery::mock('alias:Ekrembk\Post');
    }

    public function tearDown()
    {
        Mockery::close();
    }

    public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
    {
        $eloquentReturn = 'fake return';
        $this->mockEloquent->shouldReceive('all')
                     ->once()
                     ->andReturn($eloquentDongu);
        $repo = new EloquentPostRepository($this->mockEloquent);

        $allPosts = $repo->all();
        $this->assertEquals($eloquentReturn, $allPosts);
    }
}
¿Fue útil?

Solución

Tough to tell without the source of "Ekrembk\Repositories\EloquentPostRepository", but, I see a couple of issues. It looks like within your EloquentPostRepository, you're calling a static. You shouldn't do that. It makes it hard to test (as you've discovered). Assuming that Ekrembk\Post extends from Eloquent, you can do this instead:

<?php 
namespace Ekrembk\Repositories

class EloquentPostRepository {

    protected $model;

    public __construct(\Ekrembk\Post $model) {
        $this->model = $model;
    }   

    public function all()
    {
        $query = $this->model->newQuery();

        $results = $query->get();

        return $results;
    }

}

Then, your test will be simpler:

<?php

use Ekrembk\Repositories\EloquentPostRepository;

class EloquentPostRepositoryTest extends TestCase {

    public function tearDown()
    {
        Mockery::close();
    }

    public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
    {
        $mockModel = Mockery::mock('\Ekrembk\Post');
        $repo = new EloquentPostRepository($mockModel);
        $eloquentReturn = 'fake return';

        $mockModel->shouldReceive('newQuery')->once()->andReturn($mockQuery = m::mock(' \Illuminate\Database\Eloquent\Builder'));

        $result = $mockQuery->shouldReceive('get')->once()->andReeturn($eloquentReturn);

        $this->assertEquals($eloquentReturn, $result);
    }
}

Didn't test the above so it might have issues, but you should get the idea.

If you look in Illuminate\Database\Eloquent\Model, you'll see that "public static function all" is really just calling "get" on an instantiated eloquent model.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top