mardi 22 mars 2016

How to mock a trait in Laravel 5 and tests a create method on a repository?

So I am learning how to test. Firstly I am trying to understand and go by the SOLID principles because I guess that helps with testing later.

So my UserController's store method was bloated with lot of code like authorising the user, crypting the password, firing events and so on.

So after over riding the create method in my repository, it looked clean and had only one responsibility which is input and output, and looked like so:

public function store(CreateUserRequest $request)
{
    $user = $this->user->create($request->all());

    return response()->jsend(
        $data       = $user,
        $presenter  = $this->presenter,
        $status     = 'success',
        $message    = 'Resource Created Successfully',
        $code       = 201
    );
}

Note: $this->user is actually the repository instance and not the model itself.

And the create method of my user repository looks like so:

public function create(array $data)
{
    // $this->authorize('store', $this->model);
    $data['password'] = bcrypt($data['password']);
    $user = $this->model->create($data);
    event(new UserWasCreated($user));
    return $user;
}

The test case I wrote looks like so:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

use Uppdragshuset\AO\Tenant\Repositories\EloquentUserRepository;
use Uppdragshuset\AO\Tenant\Models\User;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

use Uppdragshuset\AO\Tenant\Events\UserWasCreated;

class EloquentUserRepositoryTest extends TestCase
{
    protected $user;

    public function setUp()
    {
        parent::setUp();
        $this->userRepo = new EloquentUserRepository;
    }

    public function tearDown()
    {
        Mockery::close();
    }

    public function test_create_a_new_user()
    {
        // $mock->shouldReceive('authorize')->once()->andReturn('');

        $user = factory(User::class)->make([
            'password' => 'password'
        ])->getAttributes();

        $this->expectsEvents(UserWasCreated::class);

        $user = $this->userRepo->create($user);
    }
}

So I am able to do things like $this->expectsEvents(UserWasCreated::class); and the events don't actually show up in the redis database. So I understand the basics of mocking I guess.

But notice how I have commented out the authorize method in the create method and also the mocking of it in the test because when I tried to mock the authorize method, I tried a lot of things but not many made sense to me because authorize method comes from a trait and not a class so how to mock traits and if I uncomment authorize in my create method, it gives me an error saying the user is not authorized which makes sense because there is no authorization at all. So how to mock this and am I doing all this correctly in the first place or am I creating stupid tests like amateurs?

Aucun commentaire:

Enregistrer un commentaire