php - 带有构造函数参数的 PHP 依赖注入使测试变得困难
问题描述
我正在尝试处理一些依赖注入最佳实践。我正在尝试测试使用braintree/braintree_php
作曲家库的服务类。假设我有这样的BraintreeService
课程:
namespace App\Service;
class BraintreeService
{
/* @var Braintree_Gateway */
private $gateway;
public function __construct()
{
$this->gateway = new \Braintree_Gateway([
'environment' => BRAINTREE_ENVIRONMENT,
'merchantId' => BRAINTREE_MERCHANT_ID,
'publicKey' => BRAINTREE_PUBLIC_KEY,
'privateKey' => BRAINTREE_PRIVATE_KEY,
]);
}
/*
* Generate a new client token from Braintree
*
* @return string $string
*/
public function getClientToken() : string
{
return $this->gateway->clientToken()->generate();
}
}
该类的用法将如下所示:
$btService = new \App\Service\BraintreeService();
$token = $btService->getClientToken();
明显的问题是这个服务类是紧密依赖的Braintree_Gateway
。因此,使单元测试BraintreeService
变得困难。为了使测试更容易,我想转向Braintree_Gateway
构造函数参数。这将允许我Braintree_Gateway
在单元测试中模拟课程。
但是,据我了解,如果我这样做,那么代码将如下所示:
namespace App\Service;
class BraintreeService
{
/* @var Braintree_Gateway */
private $gateway;
public function __construct(Braintree_Gateway $gateway)
{
$this->gateway = $gateway;
}
/*
* Generate a new client token from Braintree
*
* @return string $string
*/
public function getClientToken() : string
{
return $this->gateway->clientToken()->generate();
}
}
该类的用法将如下所示:
$btService = new \App\Service\BraintreeService(
new \Braintree_Gateway([
'environment' => BRAINTREE_ENVIRONMENT,
'merchantId' => BRAINTREE_MERCHANT_ID,
'publicKey' => BRAINTREE_PUBLIC_KEY,
'privateKey' => BRAINTREE_PRIVATE_KEY,
])
);
$token = $btService->getClientToken();
如果我在整个代码中的多个位置使用此服务,我觉得这会变得很麻烦。我想要一些关于如何更好地处理依赖关系同时仍然能够完全测试我的服务类的建议。谢谢!
解决方案
在构造函数中接受 null 作为默认值:
public function __construct(Braintree_Gateway $gateway=null) {
if(!gateway) {
$gateway = new \Braintree_Gateway([
'environment' => BRAINTREE_ENVIRONMENT,
'merchantId' => BRAINTREE_MERCHANT_ID,
'publicKey' => BRAINTREE_PUBLIC_KEY,
'privateKey' => BRAINTREE_PRIVATE_KEY,
]);
}
}
这样,您可以覆盖它进行测试,但在生产中保持向后兼容
推荐阅读
- java - 无法确定时间复杂度
- laravel - laravel 迁移外键可为空
- html - 元素 div 跟随鼠标位置
- javascript - 属性 circle-color 总是画黑色圆圈
- apache-spark - 从 EMR pyspark 访问 Athena View,重新创建外部表或胶水目录,最有效的方式
- javascript - Vue,动态导入模板
- docker - GitLab CI/CD - 部署图像
- c - 循环直到使用 C 输入正确的数据类型
- python - f2py 模块级字符变量长度通过来自其他模块的参数
- sql - SQL:如何在同一个团队中选择两个employeeid并且team_score大于400?提到了下面的表架构