我正在使用TDD。我需要在我的系统中使用原始SQL查询。 TDD建议我只需要测试业务逻辑(数据库,邮件发送或文件系统的所有测试都是集成测试)。所以,我将我的SQL代码放在一个我想要模拟的独立类中。这是一个代码:
// Creating shipping method data provider mock
$shippingMethodDataProviderMock = $this->getMockBuilder('\ordersmanager\Model\Order\ShippingMethod\ShippingMethodDataProvider')->disableOriginalConstructor()->getMock();
// Getting shipping method instance
$emsShippingMethod = ShippingMethodFactory::getShippingMethod('ems', $shippingMethodDataProviderMock);
但我不想在客户端代码中将ShippingMethodProvider
实例传递给ShippingMethodFactory
。
我可以使用合成而不是聚合:在ShippingMethodProvider
中创建ShippingMethodFactory
并将其传递给ShippingMethod
构造函数。但在这种情况下,我无法模拟ShippingMethodProvider
因为它与客户端代码隔离。
我可以为ShippingMethodFactory
创建一个包装器,它不会经过单元测试,但会创建一个令人愉快的API:
$emsShippingMethod = ShippingMethodFactory::getShippingMethod('ems');
但是这个包装器不会被测试。
有什么更好的方法来测试它并拥有一个好的API?
答案 0 :(得分:1)
首先,工厂和供应商听起来像是一个类似的概念,也许你需要考虑更好的名字。
我认为ShippingMethod
并不真正需要ShippingMethodProvider
。它听起来像是我的实体或价值对象。创建ShippingMethod
对象后,它已经存在,它不需要访问数据库并再次提供自己。
我会假设ShippingMethodProvider
实际上只在创建时才需要。 ShippingMethod
由ShippingMethodFactory
创建,因此需要提供者。因此,只需创建一个工厂实例并在构造函数中传递提供程序。
$provider = new ShippingMethodProvider(...);
$factory = new ShippingMethodFactory($provider);
// pass the factory wherever you need to create shipping methods and use it
$shippingMethod = $factory->createShippingMethod('ems')