How to mock a service (or a ServiceProvider) when running Feature tests in Laravel?

前端 未结 2 1420
天涯浪人
天涯浪人 2021-01-03 04:06

I\'m writing a small API in Laravel, partly for the purposes of learning this framework. I think I have spotted a gaping hole in the docs, but it may be due to my not unders

2条回答
  •  误落风尘
    2021-01-03 04:29

    Aha, I have found a temporary solution. I'll post it here, and then explain how it can be improved.

    app->bind(UsersService::class, function() {
                return new UsersDummy();
            });
    
            $response = $this->json('GET', '/v1/users');
    
            $response
                ->assertStatus(200)
                ->assertJson(['ok' => true, ]);
        }
    }
    
    class UsersDummy extends UsersService
    {
        public function listUsers()
        {
            return ['tom', 'dick', 'harry', ];
        }
    }
    

    This injects a DI binding so that the default ServiceProvider does not need to kick in. If I add some debug code to $response like so:

    /* @var $response \Illuminate\Http\JsonResponse */
    print_r($response->getData(true));
    

    then I get this output:

    Array
    (
        [ok] => 1
        [users] => Array
            (
                [0] => tom
                [1] => dick
                [2] => harry
            )
    
    )
    

    This has allowed me to create a test with a boundary drawn around the PHP, and no calls are made to the test box to interact with the user system.

    I will next investigate whether my controller's constructor can be changed from a concrete implementation hint (\App\Services\Users) to an interface, so that my test implementation does not need to extend from the real one.

提交回复
热议问题