模拟 class 在 Magento 的其他 class 中实例化
Mocking class instantiated in other class in Magento
我正在尝试学习更多关于测试的知识,但不幸的是我必须在 Magento 1.9 中进行。* :)
考虑以下代码(GDPR 相关)...
class Vendor_Module_Helper_Data
{
public function __construct()
{
$this->config = Mage::helper('vendor_module/config');
}
public function anonymizeEmail(Mage_Customer_Model_Customer $customer)
{
return preg_replace_callback('#{([a-z_]*)}#', function ($matches) use ($customer) {
return strtolower($customer->getData($matches[1]));
}, $this->config->getEmailFormat());
}
}
class Vendor_Module_Helper_Config
{
public function getEmailFormat()
{
return Mage::getStoreConfig('vendor_module/email/format));
}
}
我正在编写一个测试,断言给客户的电子邮件格式正确,如下所示:
public function it_anonymizes_customer_email()
{
$customer = Mage::getModel('customer/customer')
->setEntityId(1)
->setFirstname('Customer')
->setLastname('Anonymous');
$configStub = $this->createMock(Vendor_Module_Helper_Config::class);
$configStub->method('getEmailFormat')
->willReturn('customer.{entity_id}@anonymo.us');
$email = Mage::helper('vendor_module')->anonymizeEmail($customer);
$this->assertEquals($email, 'customer.1@anonymo.us');
}
当然这不会按原样工作,但我在这里尝试实现的目标应该很清楚...
我的问题是如何在不使用 DI 的情况下使这项工作发挥最佳效果,而 Magento 缺少这种功能。
有没有办法模拟在另一个 class 的构造函数中实例化(受保护)的 class?这是最佳做法吗?
或者这是一个有效的解决方案:
class Vendor_Module_Helper_Data
{
public function __construct($args)
{
$this->config = isset($args['config'] ? $args['config'] : Mage::helper('vendor_module/config');
}
}
然后在测试中:
$email = Mage::helper('vendor_module', ['config' => $configStub])->anonymizeEmail($customer);
我必须将 class 从助手更改为模型,因为助手不接受构造函数参数(我认为)。
一些建议将不胜感激!
在你的情况下,我认为最好有:
class Vendor_Module_Helper_Data
{
public function getConfig()
{
return Mage::helper('vendor_module/config');
}
public function anonymizeEmail(Mage_Customer_Model_Customer $customer)
{
return preg_replace_callback('#{([a-z_]*)}#', function ($matches) use ($customer) {
return strtolower($customer->getData($matches[1]));
}, $this->getConfig()->getEmailFormat());
}
}
在你的测试中:
public function it_anonymizes_customer_email()
{
$customer = Mage::getModel('customer/customer')
->setEntityId(1)
->setFirstname('Customer')
->setLastname('Anonymous');
$configStub = $this->createMock(Vendor_Module_Helper_Config::class);
$configStub->method('getEmailFormat')
->willReturn('customer.{entity_id}@anonymo.us');
$helper = $this->createMock(Vendor_Module_Helper_Data::class, ['getConfig']);
$email->expects($this->once())->method("getConfig")->willReturn($configStub);
$this->assertEquals('customer.1@anonymo.us', $helper-> anonymizeEmail($customer));
}
所以您正在创建一个方法 getConfig,然后将其模拟为 return 您创建的另一个模拟。
另一方面,对于在 Magento 1.X 中进行测试,我建议使用模块 EcomDev,这可以使测试速度更快,并允许您设置 magento 特定的固定装置。好久没维护了,但是用的还不错,可以帮你更快的写测试
我正在尝试学习更多关于测试的知识,但不幸的是我必须在 Magento 1.9 中进行。* :)
考虑以下代码(GDPR 相关)...
class Vendor_Module_Helper_Data
{
public function __construct()
{
$this->config = Mage::helper('vendor_module/config');
}
public function anonymizeEmail(Mage_Customer_Model_Customer $customer)
{
return preg_replace_callback('#{([a-z_]*)}#', function ($matches) use ($customer) {
return strtolower($customer->getData($matches[1]));
}, $this->config->getEmailFormat());
}
}
class Vendor_Module_Helper_Config
{
public function getEmailFormat()
{
return Mage::getStoreConfig('vendor_module/email/format));
}
}
我正在编写一个测试,断言给客户的电子邮件格式正确,如下所示:
public function it_anonymizes_customer_email()
{
$customer = Mage::getModel('customer/customer')
->setEntityId(1)
->setFirstname('Customer')
->setLastname('Anonymous');
$configStub = $this->createMock(Vendor_Module_Helper_Config::class);
$configStub->method('getEmailFormat')
->willReturn('customer.{entity_id}@anonymo.us');
$email = Mage::helper('vendor_module')->anonymizeEmail($customer);
$this->assertEquals($email, 'customer.1@anonymo.us');
}
当然这不会按原样工作,但我在这里尝试实现的目标应该很清楚...
我的问题是如何在不使用 DI 的情况下使这项工作发挥最佳效果,而 Magento 缺少这种功能。
有没有办法模拟在另一个 class 的构造函数中实例化(受保护)的 class?这是最佳做法吗?
或者这是一个有效的解决方案:
class Vendor_Module_Helper_Data
{
public function __construct($args)
{
$this->config = isset($args['config'] ? $args['config'] : Mage::helper('vendor_module/config');
}
}
然后在测试中:
$email = Mage::helper('vendor_module', ['config' => $configStub])->anonymizeEmail($customer);
我必须将 class 从助手更改为模型,因为助手不接受构造函数参数(我认为)。
一些建议将不胜感激!
在你的情况下,我认为最好有:
class Vendor_Module_Helper_Data
{
public function getConfig()
{
return Mage::helper('vendor_module/config');
}
public function anonymizeEmail(Mage_Customer_Model_Customer $customer)
{
return preg_replace_callback('#{([a-z_]*)}#', function ($matches) use ($customer) {
return strtolower($customer->getData($matches[1]));
}, $this->getConfig()->getEmailFormat());
}
}
在你的测试中:
public function it_anonymizes_customer_email()
{
$customer = Mage::getModel('customer/customer')
->setEntityId(1)
->setFirstname('Customer')
->setLastname('Anonymous');
$configStub = $this->createMock(Vendor_Module_Helper_Config::class);
$configStub->method('getEmailFormat')
->willReturn('customer.{entity_id}@anonymo.us');
$helper = $this->createMock(Vendor_Module_Helper_Data::class, ['getConfig']);
$email->expects($this->once())->method("getConfig")->willReturn($configStub);
$this->assertEquals('customer.1@anonymo.us', $helper-> anonymizeEmail($customer));
}
所以您正在创建一个方法 getConfig,然后将其模拟为 return 您创建的另一个模拟。
另一方面,对于在 Magento 1.X 中进行测试,我建议使用模块 EcomDev,这可以使测试速度更快,并允许您设置 magento 特定的固定装置。好久没维护了,但是用的还不错,可以帮你更快的写测试