首页 文章

在phpunit中创建一个模拟而不模拟任何方法?

提问于
浏览
33

当我用PHPUnit对我的PHP代码进行单元测试时,我试图找出模拟对象的正确方法,而不会嘲笑它的任何方法 .

问题是,如果我不调用 getMockBuilder()->setMethods() ,那么对象上的所有方法都将被模拟,我无法调用我想要测试的方法;但如果我打电话给 setMethods() ,那么我需要告诉它什么方法来模拟,但我不想模仿任何方法 . 但我需要创建模拟,这样我就可以避免在测试中调用构造函数 .

这是我想要测试的方法的一个简单示例:

class Foobar
{
    public function __construct()
    {
        // stuff happens here ...
    }

    public function myMethod($s)
    {
        // I want to test this
        return (strlen($s) > 3);
    }
}

我可能会测试 myMethod()

$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));

但这会叫Foobar的构造函数,这是我不想要的 . 所以相反,我会尝试:

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

但是在不使用 setMethods() 的情况下调用 getMockBuilder() 将导致其所有方法被模拟并返回null,因此我对 myMethod() 的调用将返回null而不触及我打算测试的代码 .

到目前为止,我的解决方法是:

$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
    ->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

这将模拟名为'none'的方法,该方法不存在,但PHPUnit并不关心 . 它会让myMethod()取消模拟,以便我可以调用它,它也会让我禁用构造函数,这样我就不会调用它 . 完善!除了必须指定一个不存在的方法名称 - “无”,或“blargh”或“xyzzy”似乎是作弊 .

这样做的正确方法是什么?

4 回答

  • -8

    您可以将 null 传递给 setMethods() 以避免模拟任何方法 . 传递一个空数组将模拟所有方法 . 后者是您找到的方法的默认值 .

    话虽如此,我想说这样做的必要性可能会指出这个类的设计存在缺陷 . 这种方法应该是静态的还是移到另一个类?如果该方法不需要完全构造的实例,则表明它可能是一个可以变为静态的实用方法 .

  • 3

    另一个hacky但简洁的解决方案就是将魔术构造函数列为模拟方法之一:

    $mock = $this->getMock('MyClass', array('__construct'));
    
  • 43

    或者你可以直接使用 getMock() .

    $mock = $this->getMock('MyClass', null, array(), null, false);

  • 0

    这对我有用:

    $this->getMock($class, array(), array(), '', false);
    

相关问题