我需要使用什么:TDD中的聚合或组合?

时间:2013-01-03 12:52:10

标签: php mocking tdd phpunit

我正在使用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?

1 个答案:

答案 0 :(得分:1)

首先,工厂和供应商听起来像是一个类似的概念,也许你需要考虑更好的名字。

我认为ShippingMethod并不真正需要ShippingMethodProvider。它听起来像是我的实体或价值对象。创建ShippingMethod对象后,它已经存在,它不需要访问数据库并再次提供自己。

我会假设ShippingMethodProvider实际上只在创建时才需要。 ShippingMethodShippingMethodFactory创建,因此需要提供者。因此,只需创建一个工厂实例并在构造函数中传递提供程序。

$provider = new ShippingMethodProvider(...);
$factory = new ShippingMethodFactory($provider);

// pass the factory wherever you need to create shipping methods and use it
$shippingMethod = $factory->createShippingMethod('ems')