0

我正在尝试学习单元测试并且遇到以下情况,我无法理解:

  1. 我有一个模型:SalesOrder - 为电子商务商店中的订单建模
  2. SalesOrder 有一个名为 gift_message_id 的属性
  3. 礼物消息 id 是一个整数值,是 GiftMessage 模型的外键
  4. GiftMessage 模型有一个方法可以采用订单模型并根据 SalesOrder 正确加载 GiftMessage 实例。

我正在尝试编写一个准确测试此行为的测试,但我最终得到了 2 个模拟:1 个用于 SalesOrder,1 个用于 GiftMessage,它没有意义。我在这里做错了什么?

我尝试测试的方法如下所示:

public function loadGiftMessageByOrderModel(SalesOrder $order)
{
    $giftMessageId = $order->getGiftMessageId();

    //if the order has a gift message id then load the gift message model and return it
    if ($giftMessageId !== false) {
        return new GiftMessage($giftMessageId);
    }
    return false;
}

如何进行单元测试,记住订单和礼品消息数据存储在数据库中。

4

2 回答 2

0

任何时候你有一个调用构造函数的方法并且在构造函数中完成了重要的工作,你就有麻烦了。我从上面看到的最好的选择是让上面的类持有一个GiftMessageFactory实例。然后,您可以模拟工厂以验证是否使用适当的值和适当的时间调用它。

于 2013-03-29T16:27:53.560 回答
0

当您编写loadGiftMessageByOrderModel函数并解释了 GiftMessage 构造函数时,我认为您不能轻松地对这段代码进行单元测试。为了干净地测试它,您需要以不是构造函数的方法从数据库加载 GiftMessage。您的构造函数不应调用与数据库交互的方法。另一个类或方法应该执行该加载,然后调用构造函数。大致是这样的:

public function loadGiftMessageByOrderModel(SalesOrder $order)
{
    $giftMessageId = $order->getGiftMessageId();

    //if the order has a gift message id then load the gift message model and return it
    if ($giftMessageId !== false) {
        // $giftMessageLoader handles loading from the DB; it doesn't create a GiftMessage object
        $giftMessageRecord = $giftMessageLoader.loadById( $giftMessageId );
        // $giftMessageFactory actually calls the constructor to create a GiftMessage
        return $giftMessageFactory.createFromRecord( $giftMessageRecord );
    }
    return false;
}

然后,您可以模拟$giftMessageLoader.loadById调用,以便控制从数据库返回的内容。您还可以测试是否正确$giftMessageFactory调用了GiftMessage构造函数并创建了正确的对象。

这里的总体教训是构造函数应该很简单。他们可以验证参数以便正确构造对象,但他们可能不应该调用应用程序的其他重要部分。

于 2013-03-31T18:46:13.087 回答