Laravel PhpUnit 依赖注入
Posted
技术标签:
【中文标题】Laravel PhpUnit 依赖注入【英文标题】:Laravel PhpUnit Dependency Injection 【发布时间】:2022-01-16 03:40:20 【问题描述】:我正在使用依赖注入来调用 Laravel 中的自定义服务,它工作正常。但是当我使用接口将这些依赖项注入我的 phpunit 测试用例类时,我收到以下错误:
目标 [App\Services\Interfaces\CarServiceInterface] 不可实例化。
虽然接口已正确绑定到提供程序中的目标具体类。
我使用了不同的样式,例如通过__construct()
方法注入、注入到测试方法甚至调用app()
方法,但它们都不起作用。
测试文件:
private $carService;
public function setUp(): void
parent::setUp();
$this->carService = app(CarServiceInterface::class);
提供者:
$this->app->bind(
App\Services\Interfaces\CarServiceInterface::class,
App\Services\CarService::class
);
这样做的正确方法是什么?
【问题讨论】:
你在哪里写你的测试?在单元测试还是在功能测试部分? @BABAKASHRAFI 在单元测试中 您需要在功能测试部分编写您的测试,因为它继承自具有CreatesApplication
特征的自定义测试用例。
@BABAKASHRAFI 好吧,我将测试移至功能部分,但我仍然收到错误。
可能是绑定错误。
【参考方案1】:
您需要在特性部分编写测试,因为特性测试是从 laravel 基本测试用例继承的,并且它们具有 CreatesApplication
特征。 Refer to here
之后,您可以在测试中使用app('Your abstract class namespace ')
方法或$this->app->make('Your abstract class namespace ')
简单地获取具体的类实例。
【讨论】:
【参考方案2】:显然是错误的测试方法。 为什么在测试课上需要 DI?! 在测试类中,您必须准备并可能绑定/模拟所需的类。 然后测试你的代码。
错误的第二部分表明,尽管您的假设,该类没有正确绑定。
顺便说一句,如果你认为我错过了什么,而你需要 DI,请使用 bind
或 singleton
方法。
$this->app->bind(CarServiceInterface::class, fn () => $exampleInstance);
//or
$this->app->singleton(CarServiceInterface::class, fn () => $exampleInstance);
现在您可以像这样使用容器访问您的界面而不会出现 DI 错误:
$this->app[CarServiceInterface::class]
//or
$this->app->make(CarServiceInterface::class)
//or
app(CarServiceInterface::class)
【讨论】:
【参考方案3】:好吧,我终于找到了问题所在。尽管其他人给出的所有答案/建议也是正确的。
我的测试用例类扩展了错误的 TestCase 命名空间。通过将其更改为App\TestCase
,它得到了修复。
【讨论】:
以上是关于Laravel PhpUnit 依赖注入的主要内容,如果未能解决你的问题,请参考以下文章