Mocking Eloquent Queries

Published 3 months ago by Havocbringer

Hello guys,

I am trying to catch up with Unit Tests. The problem is, 99% of our DB queries are using static methods of the Eloquent models, e.g.: User::join(...)->where(...)->get()

Is there any way to mock these DB calls? I seem to be hitting a rock with PHPUnit and Mockery.

Here's an example (everything is deliberately crammed inside a single method):

/** @test */
public function example()
{
    $mockedUser = \Mockery::mock(\App\Models\Admin\User::class);
    $this->app->instance(\App\Models\Admin\User::class, $mockedUser);
    $mockedBuilder = \Mockery::mock(\Illuminate\Database\Eloquent\Builder::class);
    $this->app->instance(\Illuminate\Database\Eloquent\Builder::class, $mockedUser);
    $mockedUser->shouldReceive('where')->with('id',5)->andReturn($mockedBuilder);

    $emptyUser = new \App\Models\Admin\User();
    $emptyUser->id = 2;

    $mockedBuilder->shouldReceive('first')->once()->andReturn($emptyUser);
    $newUser = \App\Models\Admin\User::where('id',5)->first();
    $this->assertEquals($emptyUser->id, $newUser->id);
}

What am I doing wrong? Is it possible to mock such queries without dependency injection or separating the DB extraction layer?

Best Answer (As Selected By Havocbringer)
tykus

Unit Testing breaks down whenever you start to mock Eloquent in my experience.

tykus
tykus
3 months ago (659,440 XP)

What are you doing; testing the eloquent builder syntax? Just use the database!

If you must test in isolation, then extract a repository (or query class), inject it into your controller(?) and mock that repository method!

Havocbringer

No, this is a simplified example, I am just trying to get it to work.

I want to be able to test methods that call the database internally. In order to be able to do so, I want to intercept the DB calls by using Mockery.

I have no problems in calling the actual test database but that would not be "unit testing".

tykus
tykus
3 months ago (659,440 XP)

Unit Testing breaks down whenever you start to mock Eloquent in my experience.

Havocbringer

That's what I was afraid of ... So the best option remains to separate the DB extraction and just test the methods independently?

tykus
tykus
3 months ago (659,440 XP)

That's how I would approach this problem if I wanted to test a query at unit level.

Please sign in or create an account to participate in this conversation.