如何抢先模拟由另一个类

时间:2016-02-03 21:36:29

标签: php unit-testing mocking phpunit

我怀疑"最好"回答我的问题是使用依赖注入并完全避免这个问题。不幸的是,我没有这个选择......

我需要为一个类编写一个测试,这个类会导致第三方库被实例化。我想模拟/存根库类,以便它不会进行实时API调用。

我在CakePHP v3.x框架中使用phpunit。我能够模拟库并创建存根响应,但这并不能阻止"真实的"从我的测试之外的代码实例化的类。我考虑过试图在实例化的上游模拟类,但是它们中有一个 lot ,这会使得测试非常难以编写/维护。

有没有办法以某种方式" stub"班级的实例化?类似于我们可以告诉php单元期望API调用并预设返回的数据的方式?

2 个答案:

答案 0 :(得分:0)

使用PHPUnit,您可以获得API类的模拟。然后,您可以指定它将如何与使用的方法和参数进行交互。

以下是phpunit.de网站(第9章)的一个例子:

public function testObserversAreUpdated()
{
    // Create a mock for the Observer class,
    // only mock the update() method.
    $observer = $this->getMockBuilder('Observer')
                     ->setMethods(array('update'))
                     ->getMock();

    // Set up the expectation for the update() method
    // to be called only once and with the string 'something'
    // as its parameter.
    $observer->expects($this->once())
             ->method('update')
             ->with($this->equalTo('something'));

    // Create a Subject object and attach the mocked
    // Observer object to it.
    $subject = new Subject('My subject');
    $subject->attach($observer);

    // Call the doSomething() method on the $subject object
    // which we expect to call the mocked Observer object's
    // update() method with the string 'something'.
    $subject->doSomething();
}

如果API返回了某些内容,那么您可以将will()添加到第二个语句中,如下所示:

   ->will($this->returnValue(TRUE));

答案 1 :(得分:0)

我怀疑你可以模仿实例化,因为' new'是一种语言构造,并且无法模拟本机功能。几乎没有什么选择可以考虑,一个值得比其他选择:

  • 模拟第三方API
  • 使用自己的代理/装饰器
  • 包装库
  • 模拟整个库并在composer中替换它以进行测试