Laravel中如何无需创建工厂模拟带构造参数的外部类做单元测试?
简化Laravel中ReCaptcha/Mailchimp的依赖注入与测试
一、移除冗余工厂类,直接绑定到容器
你之前为处理构造参数创建了工厂类,其实可以直接在AppServiceProvider里把带参数的类绑定到Laravel容器,省去工厂类和额外配置:
// App\Providers\AppServiceProvider.php public function register() { // 绑定ReCaptcha,自动注入配置的密钥 $this->app->bind(\ReCaptcha\ReCaptcha::class, function ($app) { return new \ReCaptcha\ReCaptcha(config('services.recaptcha.secret')); }); // 同理处理Mailchimp(根据它的构造参数调整) $this->app->bind(\NZTim\Mailchimp\Mailchimp::class, function ($app) { return new \NZTim\Mailchimp\Mailchimp(config('services.mailchimp.api_key')); }); }
之后控制器里直接通过容器获取实例,或者用依赖注入更规范:
// 方式1:直接从容器获取 $recaptcha = app(\ReCaptcha\ReCaptcha::class); // 方式2:构造函数依赖注入(推荐) public function __construct(private \ReCaptcha\ReCaptcha $recaptcha) {} // 方法内直接调用 $this->recaptcha->verify(...);
二、简化单元测试的模拟逻辑
原来的测试需要模拟make方法,现在容器直接返回实例,测试里只需要模拟业务方法即可:
$mock_response = // 提前准备的模拟响应对象 $this->mock(\ReCaptcha\ReCaptcha::class, function ($mock) use ($mock_response) { $mock->shouldReceive('verify') ->once() ->andReturn($mock_response); });
三、关于你提到的resolve传参方式
你说的resolve(ReCaptcha::class, ['param1'=>config('services.recaptcha.secret')])是可行的,但这种方式需要每次调用都手动传参数,适合临时创建实例的场景。如果业务代码中频繁使用,还是推荐容器绑定的方式,更简洁且符合Laravel的依赖注入规范。
内容的提问来源于stack exchange,提问作者alexmcfarlane
相关产品推荐
相关产品推荐

