Laravel 模拟多重依赖
Posted
技术标签:
【中文标题】Laravel 模拟多重依赖【英文标题】:Laravel mock multiple dependency 【发布时间】:2022-01-09 00:01:18 【问题描述】:我有一个依赖于 BillingService 的 Controller,而 BillingService 又依赖于 UserService。
我需要调用 Controller 方法 getPlans,在这个调用中我需要模拟两个函数:
BillingService 中的 loadPlans UserService 中的 getUsage这是完整的例子:
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 ?
最后,在我的测试中,我只是调用:
getJson(action([BillingPlanController::class, "getPlans"]));
在其他测试中,我能够模拟单个服务,但在这种情况下,我不知道如何编写模拟。
对不起,如果我没有提供任何“尝试”,但我真的不知道我该怎么做。
更新
我尝试使用 partialMock 和 mock,但出现此错误(调用 getUsage 时) - 使用了 partialMock,因为我只是需要模拟一个函数:
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"]));
【问题讨论】:
如果你完全模拟而不是部分模拟服务会发生什么? 我在第一个服务上使用了 partialMock,因为 getPlans 是我需要测试的真正功能 - 如果我完全模拟他,功能未定义并且我得到:收到 Mockery_3_App_Modules_Billing_Services_BillingPlanService::getPlans(),但是没有指定期望我正在调用控制器,因为在此调用之后,我也需要测试响应。它是一个集成测试 【参考方案1】:您在部分模拟中的例外是因为当您模拟 BillingPlanService
时,您不会因为 userService
是模拟而被引入。你可以简单地在模拟上设置它,我认为它应该在你的上下文中工作。
$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([]);
);
【讨论】:
同样的 :( 使用 $mock->userService = $userServiceMock 给出同样的错误.. 使用您的解决方案(以这种方式有效),我需要将 UserService 标记为公开,但我会避免公开... 我阅读了文档,似乎 set 可以提供帮助,如果没有帮助,我将在周末创建一个本地示例,看看我能做什么。我猜这是属性的组合,它是部分的。我有我编写的示例代码,它在 Mocks 而不是部分设置属性。 对于公共,它按预期工作。但正如我所说,我认为将 DI 标记为 public 是不好的。或者至少我不想要它:) 我继续试验,如果我找到了解决方案,我会写在这里。如果你也可以在 WE 中,我真的很感激。我写的代码你认为是“奇怪的”吗?有我的例子中的 DI 吗? 你的代码是干净的,没有得到私有财产的部分。有一些选项可以将其伪装成公开gist.github.com/JeffreyWay/5287312以上是关于Laravel 模拟多重依赖的主要内容,如果未能解决你的问题,请参考以下文章