【问题标题】:How to preemptively mock a class that gets instantiated by another class如何抢先模拟一个被另一个类实例化的类
【发布时间】:2016-05-13 07:25:25
【问题描述】:

我怀疑我的问题的“最佳”答案是使用依赖注入并完全避免该问题。不幸的是,我没有那个选项...

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

我在 CakePHP v3.x 框架中使用 phpunit。我能够模拟库并创建存根响应,但这并不能阻止“真实”类被我的测试之外的代码实例化。我考虑尝试从实例化上游模拟类,但它们有很多 ,这会使测试难以编写/维护。

有没有办法以某种方式“存根”类的实例化?类似于我们可以告诉 php 单元期待 API 调用并预设返回数据的方式?

【问题讨论】:

  • 您声明不能注入依赖项,但是您可以替换工厂调用的“new”语句吗?这样你就可以控制工厂并让他们返回模拟。

标签: php unit-testing mocking phpunit


【解决方案1】:

使用 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 级更上游。所以,即使它会起作用,它也会像 15 种这样的东西。除非我在这里误解了事情。
  • 有什么方法可以创建一个类别名,以便任何实例化真实类的东西都可以创建你的模拟类?
  • 如果你使用 "->will($this->returnValue($someVariable))" 那么你基本上期望 update() 将返回 $someVariable。但不会调用 update() 本身。因此,您无需超过 1 级。
【解决方案2】:

我怀疑你可以模拟实例化,因为“新”是一种语言结构,没有办法模拟本机功能。需要考虑的选项很少,一个比另一个更有价值:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多