【问题标题】:How to write spec for services that change state of entity?如何为改变实体状态的服务编写规范?
【发布时间】:2016-10-20 18:33:30
【问题描述】:

我有一个服务MoneyMover 可以改变两个实体的状态:从sender 减少amount 的钱并将这个金额添加到receiver

我还没有实现。根据 BDD,我正在为此功能编写规范:

function it_should_reduce_balance_of_sender(User $sender, User $receiver)
{
    $sender->getBalance()->willReturn(5);
    $this->moveFromSenderToReciever($sender, $receiver, 5);
    $sender->getBalance()->shouldReturn(0);
}

但我只能测试我的服务状态,而不是任何使用的预言对象。所以这个规范抛出了一个致命的错误:

调用未定义的方法 Prophecy\Prophecy\MethodProphecy::shouldReturn()

如何测试实体的状态变化?

我知道我可以使用类似的东西:

$sender->getBalance()->shouldBeCalled()->willReturn(5);
$sender->setBalance(0)->shouldBeCalled();

$this->moveFromSenderToReceiver($sender, $reciever, 5);

但如果我只想测试状态是否已更改呢?

【问题讨论】:

    标签: php unit-testing bdd phpspec


    【解决方案1】:

    您对以这种方式验证它的反感似乎并不过分。但与其试图让 phpspec 屈服于你的意愿,或许更简洁的解决方法是完全避免 setter 和 getter。像这样的东西呢?

    $sender->decreaseBalanceBy(5)->shouldBeCalled();
    
    $this->moveFromSenderToReceiver($sender, $reciever, 5);
    

    这样读起来更自然,不用担心从外部管理用户余额的状态。

    【讨论】:

      【解决方案2】:

      你没问题

      $sender->getBalance()->shouldBeCalled()->willReturn(5);
      $sender->setBalance(0)->shouldBeCalled();
      
      $this->moveFromSenderToReceiver($sender, $reciever, 5);
      

      这是正确的做法,$sender$receiver 是两个合作者。

      你需要停下来想一想:我的班级是做什么的?如果您的答案是改变特定用户的余额,那恐怕不是正确答案(*)。
      更好的做法可能是:您的班级的行为是向用户“发送消息”或“传递责任”,说他需要设置差异平衡。你在这里说绝对安全,好吧,如果我在我的班级上调用该方法,setBalancegetBalance 应该被调用(因为这是你的班级应该做的!)。

      如果您想检查余额值是否设置(或返回)正确,您必须创建另一个规范类(它将规范您的 User 类)并执行所有测试,让您对您的代码。

      这样,如果两个测试都是绿色的,那么您可以放心地依赖您所写的内容。

      请记住,PHPSpec 是一种 BDD 工具,而不是 TDD 工具,因此您必须将注意力集中在这些事情上:“我的班级的行为是什么?”是问题。

      为了完整起见,请考虑您不拥有的外部代码,例如 ORM 或 DBAL 或任何您可以用来对数据库执行 I/O 操作的代码。假设您正在测试 描述的类需要将值写入数据库:您永远不会检查是否写入了实际数据。相反,您要做的是检查是否调用了方法调用(例如writeread 或它们获得的任何名称):如果是,您可以接受,因为希望您的库有自己的测试对自己的代码和数据库之间的交互进行检查的套件。

      (*) 这不是正确答案,因为您没有直接致电$user->amount = 0。首先,这很愚蠢,因为 amount 希望是 User 类的私有成员。因此,您只是将责任转嫁给其他人(User 类,逻辑应该属于该类)。当然,在更高的抽象层次上,说你的类改变了特定用户的平衡是可以的,在这里我需要这种分离只是为了将读者的注意力集中在一个不同的观点上,这真的可以帮助理解如果您与其他工具(如 PHPUnit 或其他工具)进行比较,为什么 PHPSpec 对这种操作如此严格。

      【讨论】:

        猜你喜欢
        • 2014-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-18
        • 1970-01-01
        相关资源
        最近更新 更多