Mockery Laravel Elequent chained queries - laravel

I have a question regarding mockery in combination with Laravel.
I have sucessfully created a mockery object to mock all the public static methods such as where and find on the elequent model instance.
$userMock = \Mockery::mock('alias:App\Models\User');
This works great, however testing chained queries like I ran into some issues:
User::where("name", "test")->first()
The only solution I could find is to use mock the demeter chain using: http://docs.mockery.io/en/latest/reference/demeter_chains.html
So for example:
$userMock->shouldReceive('where->first')->andReturn($user);
But I would like to test the arguments that are provided to the where query as well:
$userMock->shouldReceive("where")->with("slug", "test")->andReturn($user);
But that is not really working since it should return the Elequent builder, any ideas how I can test this properly?

$userMock->shouldReceive('where')
->with("slug", "test")
->andReturn(Mockery::self())
->shouldReceive("first")
->andReturn($user);
Using Mockery::self you can complete the chain.

Related

Mock Laravel Model in phpunit test

I am persuing unit test and here i don't want to use the database. And i am doing mocking of each and everything. But i am unable to mock Models. If i try to mock the model with override then it gives me this error: class already exists. And if i tried without overide then the mocking is not working. I also found a trait For it named laravel query factory, which helps me to give a dummy query builder. But i am facing one issue in it. When i use count funtion on model then it gives me following error:
ErrorException: Undefined index: aggregate
Meanwhile i am not able to mock in any way, anyone please help me to do the same
Here is the model Query which i want to mock:
MyModel::where('column_name', 12)->count();

STI ::find() fails in controller but succeeds in tinker

I'm using MannikJ/laravel-sti but the following code has a different behaviour in tinker and in a controller (assuming the definitions in larevel-sti's documentation, with classes Root, Sub1 and Sub2):
Root::find(1234)
In tinker, it correctly returns an instance of Sub1. But in a controller, it returns null.
I get the correct instance in the controller if I replace the code with:
Sub1::find(1234)
Thanks to the maintainer (cf. issue #1), we found that the problem is that we use constructors in our objects but laravel-sti's trait also does. Constructors are a known issue in PHP with traits…

Laravel unit testing calling a method that calls that database

I have been trying to set up a unit test that calls a method where the database is called. I have looked up mocking and faker and am confused about what to do.
In my test I call
Logic::lookForClassificationException($exception_array, $content);
In my method there is a call to my ClassificationException model
$exceptions = ClassificationException::select('exception')->get();
I am confused about how to set up a mock for this. ClassificationException is a table that has an id, exception, previous_word, and after_word.
How do I mock or fake the setup?
One way to do tests using DB is to setup an in memory sqlite database for tests like so:
use Illuminate\Database\Capsule\Manager as DB;
protected function setUpDatabase()
{
$database = new DB;
$database->addConnection(['driver' => 'sqlite', 'database' => ':memory:']);
$database->bootEloquent();
$database->setAsGlobal();
}
Then, call this function in your setUp method of the test class.
This is just one of many possible ways and may not suit your needs. Another way would be to setup a separate database for tests and use a separate .env for tests
In my experience, tests break down when you try to mock Eloquent models

Learning WardrobeCMS source code, how do they retrieve posts without db request?

Newbie here. I'm learning Laravel and WardrobeCMS is a good one to study IMO. Just wondering if you guys could point me how they retrieve posts with requesting db?
In homepage, the HomeController has this line.
$posts = $this->posts->active(Config::get('core::wardrobe.per_page'));
In WardrobeServiceProvider, they bind PostRepoitory with DbPostRepository and here is their 'active' method.
public function active($per_page)
{
$per_page = is_numeric($per_page) ? $per_page : 5;
\Debugbar::info('calling posts active method');
return Post::with(array('tags', 'user'))
->where('active', 1)
->where('publish_date', '<=', new DateTime)
->orderBy('publish_date', 'desc')
->paginate($per_page);
}
The return statement looks like the Eloquent command but I don't see any db request in Debugbar console. How does this work? Please advise.
I am a designer trying to learn coding and Laravel 'illuminates' me. In my current dev project, I have around 4-10 db calls in each page. My goal here is to reduce db calls as much as possible and I think WardrobeCMS source code is my starting point.
Post::with()->where()->paginate(); doesn't always 'call' database?
In short: Yes it does!
Post is an Eloquent ORM because, basically every model (i.e. Post) in Laravel extends the Eloquent/Model class and this Eloquent/Model class uses Query Builder (DB in your case) class along with other classes to query the database and in your example, the Post is something like this:
class Post extends Eloquent {
// ...
}
SInce the Post class extends the Eloquent class so Post have access (inherited from Eloquent) to all (protected and public only) methods of Eloquent class, so, if the Eloquent has a function/method like this (actually has):
public function with($relation)
{
//...
}
Then the Post class can call that function/method like this:
Post::with()
So, actually Post::with()->where()->paginate() call interact with database in this case but it's not necessary that every database interaction has to be using DB::table(), instead, it's a convenient way to query the database using an ORM and don't forget that, the ORM is just a wrapper over the query builder, behind the scene, the Post Eloquent Model is using the query builder.
You should the manual instead of reading the source code of another application, once you get the basic idea then you may read source code of other Laravel applications to get some ideas that other developers uses.
Update: If you are not seeing any queries in the debugger then the application is using the caching feature of Laravel to cache database queries for a certain period of time so it can use those later without interacting with the database to speed up the process.

Symfony2 entityManager in model

I'm going to use entity_manager in my model. But entity_manager is only available in controller: throw $em = $this->get('doctrine.orm.entity_manager'). So, I have to define model methods with $em parameter. This is making phpUnit testing pretty difficult and violates application structure. For example:
class Settings
{
public static function getParam( $em, $key )
{
$em->createQuery("
SELECT s
FROM FrontendBundle:Settings s
WHERE s.param = {$key}
");
return $em->getResult();
}
}
Is there any approach to use entity_manager service in model section?
First, a starting note: by convention your Entity class should probably be singular. So, Setting, not Settings. You could argue that "settings" as a group of related settings could be seen as one entity. Still, something to bear in mind.
In Doctrine2, you would use a repository to make this type of query. In your code where you were going to call Settings::getParam, you would instead fetch the repository and query that. In symfony2, say:
// $em is your entitymanager, as you were going to pass to your method above
// $key is the key you were going to pass to your method above
$repository = $em->getRepository('\FrontendBundle\Settings');
$setting = $repository->getByParam($key);
By default, without writing any code, repositories define getByXXXX for each field in your entity.
If you have a more complicated query to make, you can extend the repository.
use Doctrine\ORM\EntityRepository;
class SettingsRepository extends EntityRepository
{
public function getBySomeComplicatedQuery() {
$sort_order = $this->getEntityManager()
->createQuery('SELECT count(s) FROM FrontendBundle\Settings s WHERE s.value > 32')
->getResult(Query::HYDRATE_SINGLE_SCALAR);
}
}
And then you'd call that method in the same way.
Others would advocate the use of a Manager object which would then not be tied to the Entity/ORM, but that's a needless complication in this case I think.
Doctrine2 is specifically designed to not let you use queries in your Entity file; Entities and EntityManagers are actually two aspects of the standard model layer, split apart to enforce best practices. See this article: http://symfony2basics.jkw.co.nz/get-symfony2-working/entities/
Queries in the Entity class
Putting queries in you entity seems odd to me. The same way as putting queries into your model class in Doctrine 1 it is not considered a good practice. Entity classes should be light.
I'm actually learning Doctrine2 and was thinking about similar problem: where to put queries?
In Doctrine 1 there are special Table classes and I was expecting something similar in Doctrine 2.
Repository Pattern
Today I learned that Doctrine 2 is using the Repository Pattern: http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#custom-repositories
However, to retrieve an instance of repository class you need to use Entity Manager. One way or another you need it.
Still, following the repository pattern seems a better choice.
In my opinion If you insist on having query method in your Entity class you have to pass an Entity Manager to it.
Testing
Why the need of passing entity manager makes it hard to test? From my experience explicit dependencies make testing easier as you can control them in the test (and mock them for example).
On the other hand passing the entity manager to every method is not right choice either. In such case I'd make the dependency obligatory and add it to the contructor.

Resources