当我使用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
您可以传递null以setMethods()避免模拟任何方法.传递一个空数组将模拟所有方法.后者是您找到的方法的默认值.
话虽如此,我想说这样做的必要性可能会指出这个类的设计存在缺陷.这种方法应该是静态的还是移到另一个类?如果该方法不需要完全构造的实例,则表明它可能是一个可以变为静态的实用方法.