Question

In my controller I'm using MyModel::where(...) which is calling the database during one of my tests. I thought that I'd be able to overload it with the following but it's still querying the database. What can I do to be sure my test is still requiring that ::where is called but returns a mocked model so I can resume testing the rest of this controller method?

MyModel::shouldReceive('where')
  ->once()
  ->with('param1', 'param2')
  ->andReturn($mockedModel);
Was it helpful?

Solution

First of all, you have to understand why you can't mock the where method. That's because the class Illuminate\Database\Eloquent\Model (Eloquent is its alias) doesn't have a where method explicitly declared. This method is called through the magic methods __callStatic and __call and is, in fact, a method of Illuminate\Database\Eloquent\Builder (sources).

Then, you have several options :

  1. You can accept to call your database in your tests and just define a real context before your assertions. Your tests will be less unitary but we can deal with that in most of the cases.

  2. @michaelcurry solution is a good one. You can build your own abstraction layer with query scopes or other architecture (injecting the query builder by yourself in the model for example) to produce a more testable code.

  3. [never tried] You can mock directly the DB facade to completely bypass the database. You will need a good understanding of the Laravel core but it could be a good way to write "pure" unit tests.

Anyway, don't hesitate to dive into the Laravel source code. The code is clear and there are just few classes really important. That's essential to really exploit the power of the framework.

OTHER TIPS

Use http://laravel.com/docs/eloquent#query-scopes and create a new function that just returns the data you want.

If you have not read it "Laravel: From Apprentice To Artisan" I would suggest it. Will help you understand how all of this is structured.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top