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

Bri*_*dig 36 phpunit mocking

当我使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我可能测试myMethod():

$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));
Run Code Online (Sandbox Code Playgroud)

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

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Dav*_*ess 46

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

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

  • 非常感谢你!看起来setMethods(null)就是我想要的; 这导致没有方法被嘲笑.另一方面,setMethods(array())似乎会导致所有方法被模拟,就像根本不使用setMethods()一样.我无法在任何地方找到这个记录.你的"空父母"是什么意思? (4认同)