Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

marbobo's avatar
Level 12

Mocking facade DB query builder `when`

Hi, I am using laravel mocking of facade to unit test my query. but I cant continue because i dont know how to create a mock for when. does anyone here have experience doing it? see code below for the example..

DB::table('users')
	->join('profiles', 'profiles.user_id', 'users.id')
	->when(true, function ($q) {
		$q->where('profiles.age', '>', 20);
	})->get();

below is my test so far..

DB::shouldReceive('table')
	->once()
	->with('users')
	->andReturnSelf();
DB::shouldReceive('join')
	->once()
	->with('profiles', 'profiles.user_id', 'users.id')
	->andReturnSelf();

but i can't continue further because of when i don't know how to create a mock for when and I can't find any resources online. I hope someone can help me with this. thank you

0 likes
6 replies
Tray2's avatar

Personally I never mock a db call but rather hit the database when I need to. For that I use an in memory sqlite database. The tests might be a tiny bit slower but I if running them in parallel it's hardly noticable.

1 like
marbobo's avatar
Level 12

@Tray2 yes I use the that also on feature tests but we have a convention that we need to create a unit test per repository to mock each query we created.

Tray2's avatar

@marbobo So you need to both test it as a unit and as a feature. That in my mind is a bit of a waste and it's not DRY. However I do understand that it's a standard that you need to follow.

bugsysha's avatar

It is better if you explain what are you trying to do and what is this test about. Then someone can give far better answer.

1 like
marbobo's avatar
Level 12

@bugsysha what I am trying to do is to create a unit tests for those query. but I can't continue to create mocks because of the when function that I do not know how to create mock for when

bugsysha's avatar

@marbobo you need to abstract and encapsulate that logic somewhere and then you do real tests as it was already suggested.

class SomeClass
{
    public static function someMethod(bool $something): Collection
    {
        return DB::table('users')
            ->join('profiles', 'profiles.user_id', 'users.id')
            ->when($something, function (Builder $q): void {
                $q->where('profiles.age', '>', 20);
            })
            ->get();
    }
}

Then in your test

public function test_results_when_something_is_true(): void
{
    // use factories here to control the results
    $this->assertEmpty(SomeClass::someMethod(true));
}

public function test_results_when_something_is_false(): void
{
    // use factories here to control the results
    $this->assertNotEmpty(SomeClass::someMethod(false));
}

Please or to participate in this conversation.