当我用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 回答
您可以将
null
传递给setMethods()
以避免模拟任何方法 . 传递一个空数组将模拟所有方法 . 后者是您找到的方法的默认值 .话虽如此,我想说这样做的必要性可能会指出这个类的设计存在缺陷 . 这种方法应该是静态的还是移到另一个类?如果该方法不需要完全构造的实例,则表明它可能是一个可以变为静态的实用方法 .
另一个hacky但简洁的解决方案就是将魔术构造函数列为模拟方法之一:
或者你可以直接使用
getMock()
.$mock = $this->getMock('MyClass', null, array(), null, false);
这对我有用: