ellipsesynergie / api-response

Simple package to handle response properly in your API.
MIT License
377 stars 53 forks source link

Testing withPaginator method #32

Closed emir closed 7 years ago

emir commented 7 years ago

Hello! I try to test my controller but I couldn't mock response's withPaginator method. I saw that method coming from Laravel's specific Response class. So I don't know how can I test that response line. Should I change Interface or is there any clean way to do?

Here's the code I would like to tests:

return $this->response->withPaginator(Test::paginate(20), new BarTransformer());

It's my test method:

public function testIfRequestHasNotSearchQuery()
{
    $response = Mockery::mock('EllipseSynergie\ApiResponse\Contracts\Response');

    $this->app->instance(\EllipseSynergie\ApiResponse\Contracts\Response::class, $response);

    $paginator = new LengthAwarePaginator(['foo'], 1, 1, 1);
    $barTransformer = new \Foo\Transformers\BarTransformer($paginator);

    $response->shouldReceive('withPaginator')->with($paginator, $barTransformer)->andReturn('foo');

    $response = $this->json('GET', '/api/v1/foo', [], [
        'token' => 'foobarbaz'
    ]);

    $this->assertResponseOk($response);
}

Runned test log:

[2016-12-02 08:29:47] testing.INFO: {}  
[2016-12-02 08:30:13] testing.ERROR: Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_3_EllipseSynergie_ApiResponse_Contracts_Response::withPaginator(object(Illuminate\Pagination\LengthAwarePaginator), object(Foo\Transformers\BarTransformer)). Either the method was unexpected or its arguments matched no expected argument list for this method

Thanks for helping!

maximebeaudoin commented 7 years ago

Yes you can mock response. However, you need to pass exactly the same instance to the withPaginator method when you try to test them using $response->shouldReceive('withPaginator')->with().

You test fail because the $barTransformer = new \Foo\Transformers\BarTransformer($paginator); is not the same instance then the one created in your controller $this->response->withPaginator(Test::paginate(20), new BarTransformer());. Same thing for Test::paginate(20).

I think the best way to resolve this is to validate the input like this $response->shouldReceive('withPaginator')->with(Mockery::type(LengthAwarePaginator::class), Mockery::type(BarTransformer::class))->andReturn('foo');

Hope it's make sense to you !