Php 单元测试模拟-对我来说没有意义
我正在尝试学习单元测试,但遇到了以下情况,我无法理解:Php 单元测试模拟-对我来说没有意义,php,unit-testing,junit,mocking,phpunit,Php,Unit Testing,Junit,Mocking,Phpunit,我正在尝试学习单元测试,但遇到了以下情况,我无法理解: 我有一个模型:SalesOrder——它在电子商务商店中模拟订单 SalesOrder有一个名为gift\u message\u id的属性 礼品消息id是一个整数值,是礼品消息模型的外键 GiftMessage模型有一种方法,可以采用订单模型并基于SalesOrder正确加载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;
}
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;
}
考虑到订单和礼品信息数据存储在数据库中,如何对其进行单元测试。每当您有一个调用构造函数的方法,并且在构造函数中完成了非平凡的工作时,您都会遇到麻烦。我从上面看到的最佳选择是让上面的类保存一个
GiftMessageFactory
实例。然后,您可以模拟工厂以验证是否使用适当的值和适当的时间调用它。由于您已经编写了loadGiftMessageByOrderModel
函数并解释了GiftMessage构造函数,我认为您无法轻松地对该代码进行单元测试。为了干净地测试它,您需要以而不是构造函数的方法从DB加载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;
}
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
构造函数并创建正确的对象
这里的总的教训是构造函数应该很简单。他们可以验证参数,以便正确构造对象,但他们可能不应该调用应用程序的其他重要部分。我同意,单元测试是一个笑话,我认为它很有价值-但我只是不知道如何做到这一点,并使测试有价值,老实说,我真的不明白你的描述和你到底想测试什么。通常,如果要测试类X,可以模拟或实例化所有外部实体,而不管这些实体有多少。当然,保持松散耦合在这里是一个优势。我想测试一下,如果订单有礼品消息id,那么会返回礼品消息模型,否则会返回false。我可以很容易地模拟SalesOrder模型来返回礼物消息id。我不知道如何从该id加载新的礼物消息并返回它。这是因为GiftMessage构造函数获取一个id并从数据库加载它。您如何将db连接传递到
GiftMessage
对象?这里有一些全局状态,这使得您的系统很难被测试,并且可能真的有问题。