zer*_*kms 13 php testing phpunit unit-testing
在phpunit中我们可以指定特别调用的方法
->with($this->equalTo('foobar'))
Run Code Online (Sandbox Code Playgroud)
或任何
->with($this->anything())
Run Code Online (Sandbox Code Playgroud)
参数.
但是有没有办法指定该方法在没有参数的情况下被调用?
这是我期望失败的测试:
public function testZ()
{
$a = $this->getMock('q');
$a->expects($this->once())
->method('z')
->with(); // <--- what constraint to specify here?
$a->z(1);
}
Run Code Online (Sandbox Code Playgroud)
UPD:
这个问题具有理论性质,所以我没有任何现实生活的例子.在某些情况下,我现在可以想到的是:
public function testMe($object)
{
$object->foo();
}
Run Code Online (Sandbox Code Playgroud)
我们假设testMe应该(通过设计和需求)总是调用没有参数的方法(假设foo()有默认值).因为在这种情况下任何非默认参数(更精确:任何参数!=默认参数,我们还不知道,哪些可能可以独立改变)会导致致命的后果.
虽然rdlowrey是正确的,with()但没有规定检查没有传递参数,问题不在于PHPUnit而在于PHP本身.
首先,如果您的方法没有提供默认值,如果您没有传递任何参数,解释器将引发致命错误.这是预期的,与手头的问题并不完全相关,但重要的是事先说明.
其次,如果您的方法确实提供了默认值,则调用不带参数的方法将导致PHP在PHPUnit涉及传递默认值之前更改调用.这是一个简单的测试,演示PHP在PHP检查参数之前插入自身.知道PHP创建的模拟类与模拟类具有相同的签名(包括默认值)是关键.
class MockTest extends PHPUnit_Framework_TestCase {
public function test() {
$mock = $this->getMock('Foo', array('bar'));
$mock->expects($this->once())
->method('bar')
->with() // does nothing, but it doesn't matter
->will($this->returnArgument(0));
self::assertEquals('foobar', $mock->bar()); // PHP inserts 1 and 2
// assertion fails because 1 != 'foobar'
}
}
class Foo {
public function bar($x = 1, $y = 2) {
return $x + $y;
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着您可以验证是否已传递任何内容或传递了默认值,但您无法更具体.
你能解决这个限制吗?您可以在重写方法时从参数中删除默认值,因此您应该能够创建子类并对其进行模拟.这值得么?我最初的直觉反应是,这是一个巨大的代码味道.您的设计或测试都是错误的(tm).
如果你能提供一个真实的,具体的例子,你真的需要做这种测试,那么花一些时间思考一个解决方案是值得的.在那之前,我对"不要那样做"的纯粹学术回答感到满意.:)