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 understanding the "Laravel way" to do what I want.
I am writing an HTTP API to, amongst other things, list, create and delete system users on a Linux server. The structure is like so:
- Routes to
/v1/users
connectGET
,POST
andDELETE
verbs to controller methodsget
,create
anddelete
respectively. - The controller
App\Http\Controllers\UserController
does not actually run system calls, that is done by a serviceApp\Services\Users
. - The service is created by a ServiceProvider
App\Providers\Server\Users
that registers asingleton
of the service on a deferred basis. - The service is instantiated by Laravel automatically and auto-injected into the controller's constructor.
OK, so this all works. I have also written some test code, like so:
public function testGetUsers()
{
$response = $this->json('GET', '/v1/users');
/* @var $response \Illuminate\Http\JsonResponse */
$response
->assertStatus(200)
->assertJson(['ok' => true, ]);
}
This also works fine. However, this uses the normal bindings for the UserService
, and I want to put a dummy/mock in here instead.
I think I need to change my UserService
to an interface, which is easy, but I am not sure how to tell the underlying test system that I want it to run my controller, but with a non-standard service. I see App::bind()
cropping up in Stack Overflow answers when researching this, but App
is not automatically in scope in artisan-generated tests, so it feels like clutching at straws.
How can I instantiate a dummy service and then send it to Laravel when testing, so it does not use the standard ServiceProvider instead?