Back

Lumen 5.5 - Testing and mocking repositories


Hi all,

I am having a hard time to test my rest api app, I think the main reason is because of https://laravel-news.com/request-object-changes-in-lumen-5-4

Basically I have a middleware that takes care of understanding the request (authentication, version and desired output). I am using the Repository pattern, binding interfaces to specific classes (depending on the version in the request) and passing them in the constructor of my controllers. So for example my bindings look like this


    $version = getVersionFromRequest(...)
    app()->bind(SomeInterface::class, \App\Repositories\{$version}\SomeImplementation::class)

At first I had the above code in a ServiceProvider, but after few (wasted) hours trying to make it work I stumbled on the post I linked above, so basically in Lumen the Request is empty when getting to a ServiceProvider. The advice found was to move the code of the provider into a middleware. Everything was working great at that point, I didn't like the idea to do bindings in a middleware but if this is the only way.....

Problems come when mocking the "SomeInterface::class" in tests.


    class OrderTest extends TestCase
    {
        public function setUp()
        {
        parent::setUp();

        $this->mock = $this->mock(\App\Repositories\Contracts\OrderRepository::class);
    }

    public function testOrdersListShouldNotFail()
    {
        $this->get('/orders', $this->getHeaders())->seeJson([
            'status' => 'success',
        ]);

        $this->mock->shouldReceive('all')->once();

        $this->assertEquals(200, $this->response->status());
    }

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

And the error I am getting when running my tests is


    Mockery\Exception\InvalidCountException: Method all() from Mockery_0_App_Repositories_Contracts_OrderRepository should be called
    exactly 1 times but called 0 times.

My guess is that because the binding happens at the middleware level, my mock in the setUp method is being overwritten.

This is the middleware that does the bindings


    public function handle($request, Closure $next)
    {
        $api = $request->get('_api');

        foreach ($this->bindings as $interface => $implementation) {
            $implementation = implode('\\', ['App', 'Repositories', $api->version(), $implementation]);
            app()->bind($interface, $implementation);
        }

        return $next($request);
    }

And this is my controller constructor


    public function __construct(OrderRepository $order)
    {
        $this->order = $order;

        parent::__construct();
    }

Any advice?


Sign in to participate in this thread!



We'd like to thank these amazing companies for supporting us