When writing tests in Laravel, it is common to encounter scenarios where you need to mock database queries to avoid hitting the actual database. One of the tools for this in PHP is Mockery. In this blog post, we’ll break down a piece of Mockery-based test setup that allows us to mock database interactions in Laravel.

To mock the DB::raw method, you can do this:

DB::shouldReceive('raw')
    ->andReturnUsing(fn ($expression) => new Expression($expression));

This ensures that if any part of the code being tested calls DB::raw(), it does not break the test, but instead, returns a valid mockable expression.

We can do the same with the query builder:

$queryMock = Mockery::mock(Builder::class);
$queryMock->shouldReceive('where')->andReturnSelf();
$queryMock->shouldReceive('whereIntegerInRaw')->andReturnSelf();
$queryMock->shouldReceive('when')->andReturnSelf();
$queryMock->shouldReceive('pluck')->with('id')->andReturn(collect(1, 2, 3));

This allows us to simulate database query calls without actually executing SQL queries. We chain multiple method expectations:

  • where(), whereIntegerInRaw(), and when() are expected to return $this (self), allowing method chaining to behave as it does in real queries.
  • pluck('id') is set up to return a Collection containing a list of IDs, ensuring that the test code receives a predictable response.

You can also mock the database connection itself if needed:

$dbMock = Mockery::mock(Connection::class);
dbMock->shouldReceive('table')->with('posts')->andReturn($queryMock);
DB::shouldReceive('connection')->with('connection-name')->andReturn($dbMock);

This creates a mock for the database connection and sets an expectation that when the table('posts') method is called, it will return our previously defined queryMock. This effectively allows us to simulate query execution on the posts table.

Finally, we mock the DB::connection() method to return our mocked database connection when called with 'connection-name'. This is particularly useful in applications using multiple database connections.