【问题标题】:How to partially mock a class using Mockery?如何使用 Mockery 部分模拟课程?
【发布时间】:2013-07-29 19:51:21
【问题描述】:

我有这门课:

class PagSeguro {

    public function pay()
    {
        if ( ! $this->checkAllData() )
        {
            return false;
        }

        return $this->buildPaymentURL();
    }

    private function checkAllData()
    {
        return true;
    }

    private function buildPaymentURL()
    {
        echo "not cool!\n\n";

        return true;
    }

}

还有这个测试:

public function testPagSeguroPaymentData()
{
    $m = m::mock('PagSeguro[buildPaymentURL]');

    $m->shouldReceive('buildPaymentURL')
        ->once()
        ->andReturn('http://');

    $this->assertEquals($m->pay(), 'http://');
}

如果我 var_dump($m) 我看到了模拟方法:

    'buildPaymentURL' =>
    class Mockery\ExpectationDirector#1507 (5) {
      protected $_name =>
      string(15) "buildPaymentURL"
      protected $_mock =>
              ...

      protected $_expectations =>
      array(1) {
        ...
      }
      protected $_expectedOrder =>
      NULL
      protected $_defaults =>
      array(0) {
        ...
      }
    }
  }

但是当测试执行时,它调用的不是模拟的,而是真实的。除非我重命名它

private function buildPaymentURL_RENAMED() {}

然后我得到一个绿色。

谁能告诉我使用 Mockery 进行部分模拟的正确方法?

【问题讨论】:

    标签: php laravel laravel-4 mockery


    【解决方案1】:

    我认为你不能让那个方法是private,因为当你输入你的真实对象的代码时,对$this->buildPaymentURL的任何调用都必须以那个真正的私有方法结束。

    使其受到保护。这样,mock 可以扩展你的类并覆盖函数。

    另一方面,如果需要这种部分模拟,我总是有一种不好的感觉。它们很可能是糟糕设计的标志。似乎这个私有方法应该包含在它自己的一个专门处理 URL 创建的对象中(并且可以单独测试),并且您现在正在测试的这个类应该只获得注入的新类的完整模拟。

    【讨论】:

    • 必须公开它才能工作,因为受保护的行为是相同的。关于设计:这个类的全部目的实际上是这个 URL,它上面还有其他方法可以将数据放在一起,但是“支付”部分是由这个方法完成的,它调用了一个外部库,它与支付服务进行对话(帕格塞古罗)。不过谢谢你的建议,反正肯定有问题。 :)
    • 好的,如果它调用一个外部库,模拟那个库!
    • 太棒了。会做的。再次感谢。
    猜你喜欢
    • 2020-05-10
    • 2018-03-26
    • 2018-09-13
    • 2015-08-15
    • 2015-12-23
    • 2014-11-05
    • 2018-07-02
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多