0

I have a Controller that has a dependency with BillingService, and BillingService has another dependency on UserService.

I need to call the Controller method getPlans and in this call I need to mock two functions:

  • loadPlans that is inside BillingService
  • getUsage that is in UserService

This is the full example:

class BillingPlanController
{
    public function __construct(private BillingPlanService $billingPlanService)
    {
    }

    public function getPlans()
    {
        $plans = $this->billingPlanService->getPlans();
        //
    }
}

class BillingPlanService
{
    public function __construct(private UserService $userService)
    {
    }

    public function getPlans()
    {
        $plans = $this->loadPlans();

        $user = auth()->user();
        $usage = $this->userService->getUsage(user); // DO SOMETHING, NEED TO MOCK .. HOW ?
    }

    public function loadPlans()
    {
        // DO SOMETHING, NEED TO MOCK .. HOW ?
    }
}

At the end, in my test i simply call:

getJson(action([BillingPlanController::class, "getPlans"]));

In other tests, I'm able to mock a single Service, but in this scenario, I don't know how to write the mocks.

Sorry if I don't provide any "tries", but I really don't know how I can do that.

UPDATE

I tried to use partialMock and mock, but I get this error (when getUsage is called) - partialMock is used because i just need to mock a single function:

Typed property App\Modules\Billing\Services\BillingPlanService::$userService must not be accessed before initialization

$this->mock(UserService::class, function ($mock) {
     $mock->shouldReceive("getUsage")->andReturn([]);
});

$this->partialMock(BillingPlanService::class, function ($mock) {
   $mock->shouldReceive("loadPlans")->andReturn([]);
});

getJson(action([BillingPlanController::class, "getPlans"]));

     
Mistre83
  • 2,677
  • 6
  • 40
  • 77
  • What happens if you mock both service fully and not partial? – mrhn Dec 02 '21 at 13:51
  • I used partialMock on the first Service because the getPlans is the real function I need to test - if i full mock him the function is not defined and i get: Received Mockery_3_App_Modules_Billing_Services_BillingPlanService::getPlans(), but no expectations were specified I'm calling the controller because after this call, i need to test the response too. Its an integration test – Mistre83 Dec 02 '21 at 13:53

1 Answers1

1

Your exception in your partial mock, is because when you mock the BillingPlanService you do not intilize the userService due to it being a mock. You can simply set it on the mock and i think it should work in your context.

$userServiceMock = $this->mock(UserService::class, function ($mock) {
    $mock->shouldReceive("getUsage")->andReturn([]);
});

$this->partialMock(BillingPlanService::class, function ($userServiceMock) use ($userServiceMock) {
    $mock->set('userService', $userServiceMock);
    $mock->shouldReceive("loadPlans")->andReturn([]);
});
mrhn
  • 17,961
  • 4
  • 27
  • 46
  • The same :( using $mock->userService = $userServiceMock give the same error.. – Mistre83 Dec 02 '21 at 14:00
  • Using your solution (in this way works), i need to mark the UserService as public, but i would avoid to make this public... – Mistre83 Dec 02 '21 at 14:02
  • I read the documentation and seems that maybe set can help, try that if that won't help i will create an local example over the weekend and see what i can do. I'm guessing it is the combination of properties and it being partial. I have example code i have written thats sets properties thou on Mocks and not partials. – mrhn Dec 02 '21 at 14:05
  • With public, it work as expected. But as i said, i think is bad mark the DI as public.. or at least i dont want it :) I continue to experiment and i wrote here if i found a solution. If you can too in WE, i really appreciate. The code i wrote you think is something "strange"? Have the DI as in my example ? – Mistre83 Dec 02 '21 at 14:07
  • Your code is clean, didn't get the part with private property. There is some options to fake it to be public https://gist.github.com/JeffreyWay/5287312 – mrhn Dec 02 '21 at 14:59
  • oh.. this is a nice trick! – Mistre83 Dec 02 '21 at 15:21