我试图创建我的第一个phpunit测试,发现自己需要在IMailer
接口上存根方法。
interface IMailer
{
public function send($to, $from, $cc, $subject, $body);
public function sent();
}
$mailer = $this->getMockBuilder(
'IMailer',
array('send', 'sent'))->getMock();
$mailer->method('send')->willRreturn(0);
然而,我一直在
PHP Fatal error:
Call to undefined method Mock_Mailer_13fc0a04::method()
in ...Test.php on line 16
var_dump($mailer);
导致
class Mock_IMailer_4c3e02a7#215 (1) {
private $__phpunit_invocationMocker =>
NULL
}
使用expect($this->any())
会出现dito错误 - 似乎被模拟的对象没有任何模拟功能......
我在ubuntu盒子上运行phpunit 3.7.28和php 5.5.9。
为什么?我该如何解决?
答案 0 :(得分:5)
getMockBuilder函数仅接受className作为参数。初始化模拟对象方法的正确方法是使用setMethods函数(参见phpunit docs)
$mailer = $this->getMockBuilder('IMailer')
->setMethods(array('send', 'sent'))
->getMock();
此外,您可能希望在使用模拟对象时也有一些预期定义:
$mailer->expects($this->any())
->method('send')
->willReturn(0);
修改强>
以上适用于较新的phpunit版本。对于phpunit 3.7.28,模拟对象的使用有点不同(即期望似乎是强制性的,而且还没有返回)。对于3.7.28版本,您应将第二部分修改为:
$mailer->expects($this->any())
->method('send')
->will($this->returnValue(0));
我建议更新到以后的phpunit版本,因为在这个旧版本中找到文档似乎有些困难。
答案 1 :(得分:0)
对于仍在使用旧版本的PHPUnit但仍希望能够直接调用method()
的任何人来说,替代解决方案是覆盖默认的模拟对象类模板。
复制MockObject/Generator/mocked_class.tpl.dist
,并将副本命名为mocked_class.tpl
。然后,只需将the code for the method()
method添加到模板中:
public function method()
{
$any = new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
$expects = $this->expects($any);
$args = func_get_args();
return call_user_func_array(array($expects, 'method'), $args);
}
这样您就可以直接致电$mock->method()
了。但是,您仍需要使用->will($this->returnValue(0))
而不是->willReturn(0)
。为此,您需要引入自定义调用构建器和调用模拟器:
class My_MockObject_Builder_InvocationMocker
extends PHPUnit_Framework_MockObject_Builder_InvocationMocker {
public function willReturn( $value ) {
return $this->will( new PHPUnit_Framework_MockObject_Stub_Return( $value ) );
}
}
class My_MockObject_InvocationMocker
extends PHPUnit_Framework_MockObject_InvocationMocker {
public function expects( PHPUnit_Framework_MockObject_Matcher_Invocation $matcher ) {
return new My_MockObject_Builder_InvocationMocker($this, $matcher);
}
}
再次更新您的模板,使用My_MockObject_InvocationMocker
代替PHPUnit_Framework_MockObject_InvocationMocker
。
完整的模板将如下所示:
{prologue}{class_declaration}
{
protected static $staticInvocationMocker;
protected $invocationMocker;
{clone}{mocked_methods}
public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
{
return $this->__phpunit_getInvocationMocker()->expects($matcher);
}
public function method()
{
$any = new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
$expects = $this->expects($any);
$args = func_get_args();
return call_user_func_array(array($expects, 'method'), $args );
}
public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
{
return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
}
public function __phpunit_getInvocationMocker()
{
if ($this->invocationMocker === NULL) {
$this->invocationMocker = new My_MockObject_InvocationMocker;
}
return $this->invocationMocker;
}
public static function __phpunit_getStaticInvocationMocker()
{
if (self::$staticInvocationMocker === NULL) {
self::$staticInvocationMocker = new My_MockObject_InvocationMocker;
}
return self::$staticInvocationMocker;
}
public function __phpunit_hasMatchers()
{
return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
$this->__phpunit_getInvocationMocker()->hasMatchers();
}
public function __phpunit_verify()
{
self::__phpunit_getStaticInvocationMocker()->verify();
$this->__phpunit_getInvocationMocker()->verify();
}
public function __phpunit_cleanup()
{
self::$staticInvocationMocker = NULL;
$this->invocationMocker = NULL;
}
}{epilogue}