【问题标题】:Can you check how many times a function is called without getMock in PHPUnit你能检查在 PHPUnit 中没有 getMock 的情况下调用了多少次函数吗
【发布时间】:2012-05-11 04:38:44
【问题描述】:

我的测试套件在对象 A 中调用 accepted。然后,该函数将为对象 B 调用 insert 一定次数,具体取决于我正在运行的测试。

我想验证insert 在每次测试中被调用的次数是否正确。我不认为我可以使用模拟来计算它,因为对象 A 在我的测试中不会碰到模拟。

我在 2 年前看到了这个问题: PHPUnit Test How Many Times A Function Is Called

使用全局变量进行计数并不理想,因为我的类中不应该有专门用于类的代码。

编辑

注意insert 是静态的可能会有所帮助。即使我模拟该类并指定我只想模拟该函数,它仍然会在模拟对象上调用new,这是我面临的另一个障碍。

回答 答案是不。我只是希望@zerkms 给出这个答案,因为他是帮助我的人,所以我可以接受。

我最终发现我只能使用一个对象,但确实遇到了另一个障碍: Why isn't PHPUnit counting this function as having ran?

【问题讨论】:

  • 现在你明白为什么静态是邪恶的了 :-)
  • 我只是在研究这个时看到了一些对静态方法的厌恶。制作一个空对象然后在其上调用实例方法是否正确?

标签: php phpunit


【解决方案1】:

在这种特殊情况下似乎是不可能的。

但在某些特定情况下,您可以模拟静态方法:http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html

class Foo
{
    public static function doSomething()
    {
        return static::helper();
    }

    public static function helper()
    {
        return 'foo';
    }
}

测试:

public function testQQQ()
{
    $class = $this->getMockClass(
        'Foo',          /* name of class to mock     */
        array('helper') /* list of methods to mock   */
    );

    $class::staticExpects($this->exactly(2))
        ->method('helper')
        ->will($this->returnValue('bar'));

    $this->assertEquals(
        'bar',
        $class::doSomething()
    );
}

结果:

$ phpunit --filter QQQ
PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /var/www/.../phpunit.xml

F

Time: 1 second, Memory: 10.75Mb

There was 1 failure:

1) ...::testQQQ
Expectation failed for method name is equal to <string:helper> when invoked 2 time(s).
Method was expected to be called 2 times, actually called 1 times.


FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

【讨论】:

  • 那是我刚刚读到的那篇抨击静态的文章 :) 当我模拟静态函数时,它仍然在我的对象上调用 new。此外,即使我模拟静态函数,我认为我的其他对象也无法访问它。我的其他对象不会引用$class
  • @Dave Stein:我不确定我是否了解情况。您说您需要计算静态方法的调用次数。这里是
  • "我的另一个对象不会引用 $class" --- 它不应该有。您在测试方法中设置了一个模拟
  • 我不擅长解释事情,所以感谢您与我交谈。我的测试是针对对象 B。我调用对象 A 中的一个方法,该方法调用对象 B 中的静态方法。静态方法只是根据对象 A 的信息填充一个表。所以我的测试是调用对象 A 的方法,该方法调用 B。然后我验证 B 的最后一行是否正确。我还想验证该方法是否只被调用过一次。
  • @Dave Stein:所以上面的例子看起来和你刚才解释的很相似
【解决方案2】:

您可以使用runkit 动态重新定义静态方法(但您可能不应该这样做)。除此之外,您将不得不重组代码。要么使用非静态调用和依赖注入(因此对象 A 从外部源接收对象 B,并且您的测试可以改为通过模拟)或使用依赖注入容器,以便不连接类名并且您的测试可以创建一个模拟子类并让 A 类使用它(这更混乱,但您的非测试代码需要更少的更改,因为您可以让您的方法保持静态)。

【讨论】:

  • 我在一些帖子中听说过 runkit,它似乎是不可以使用的东西(甚至你说不要同时使用它)。我能够重组代码,但仍然遇到我在这里询问的一些障碍:stackoverflow.com/questions/10541683/…
猜你喜欢
  • 1970-01-01
  • 2012-03-17
  • 2013-08-17
  • 2011-12-15
  • 2011-05-29
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多