Introducing Mockery Testing Helpers - mock and spy

laravel provider us 2 helpers for mockery testing mock and spy.

if we have to bypass a function in the test then mockery comes in play.

imagine we have Newsletter::class to subscribe newsletter and there's API calling so if we hit api with every call our test will be slow and clould be api ratelimit issue.

namespace App;

class Newsletter {
    public function subscribeTo($name, $user)
    {
        // Make HTTP request to add user to the named newsletter.
        var_dump('making slow network request!!!');
    }
}

and here's our route where we are using this class.

Route::get('/test', function (Newsletter $newsletter) {
    $newsletter->subscribeTo('members', auth()->user());

    return 'Done';
})->middleware('auth');

and now we will write our test from start to end to understand the concept.

/** @test */
public function it_subscribe_a_user_to_a_mailing_list()
{
    $user = factory(User::class)->create();

    # Method 1
    $mock = Mockery::mock(Newsletter::class);
    $mock->shouldReceive('subscribeTo')->with('members', $user)->once();

    $this->instance(Newsletter::class, $mock);

    # Method 2
    $this->instance(Newsletter::class, Mockery::mock(Newsletter::class, function ($mock) use ($user) {
        $mock->shouldReceive()->subscribeTo('members', $user)->once();
    });

    # Method 3 - with mock helper
    $this->mock(Newsletter::class, function ($mock) use ($user) {
        $mock->shouldReceive()->subscribeTo('members', $user)->once();
    });

    $this->actingAs($user)->get('/test');
}

spy helper is little different because we need to call spy after hitting the request otherwise it won't work.

we need to call mock before hitting the request and spy after hitting the request.

/** @test */
public function it_subscribe_a_user_to_a_mailing_list()
{
    $spy = $this->spy(Newsletter::class);

    $this->actingAs($user = factory(User::class)->create())
        ->get('/test');

    $spy->shouldHaveReceived()->subscribeTo('members', $user);
}