skip to Main Content

I want to mock a service who call a third party, but I can’t figure it out.

I have a controller method who has a service injected on it and do stuff:

public function store(Request $request, MyService $myService)
{
    $data = $request->validated();

    $myService->create($data, $request->user());

    return response()->json();
}

In this service, I call a job to do other stuffs:

MyJob::dispatch($manager);

My job is built like this:

public function __construct(private Manager $manager)
{
}

public function handle()
{
    // THE SERVICE I WANT TO MOCK
    $this->managementService = resolve(ManagementService::class, ['manager_id' => $this->manager->id]);
    $this->doStuff();
}

private function doStuff() {
    $this->managementService->startManagement();
}

In ManagementService I want to mock the function callApi:

public function startManagement()
{
    $data = $this->callApi('/thirdparty/call');

    return $data;
}

SO, in my test I try to mock the ManagementService and call my route who do all these things

$this->mock(ManagementService::class, function ($mock) {
    $mock->shouldReceive('callApi')->andReturn('none');
});

$response = $this->actingAs(User::factory()->create())->post('/myroute', [
    'manager_id' => 4,
]);

But it seems this mock is never used, it’s still going into the "normal" Management Service, because when I dump $data in the startManagement method when I launch tests, it’s not returning ‘none’.

What am I doing wrong?

Thanks

2

Answers


  1. Chosen as BEST ANSWER

    Figured it out by injecting my service directly in the job

    MyJob::dispatch($manager, resolve(ManagementService::class,  ['manager_id' => $this->manager->id]));
    

    And inside the service instance it via constructor instead of in the handle

    public function __construct(public Manager $manager, ManagementService $managementService)
    {
        $this->managementService = $managementService;
    }
    

    Then in my test, my mock is instancied like this:

    $mock = Mockery::mock(ManagementService::class);
            $mock->shouldReceive('callApi')
                 ->once()
                 ->andReturn('none');
    

    Thanks to all


  2. The code that you post is not very clear but if i understand correctly you like to mock a hard dependency thats why your mock never called because you never register it.

    Just add the string overload before the class name in the mock method.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search