检查是否在没有传递任何参数的情况下调用mock的方法(在phpunit中)

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()有默认值).因为在这种情况下任何非默认参数(更精确:任何参数!=默认参数,我们还不知道,哪些可能可以独立改变)会导致致命的后果.

Dav*_*ess 7

虽然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)

这意味着您可以验证是否已传递任何内容或传递了默认值,但您无法更具体.

你能解决这个限制吗?您可以在重写方法时从参数中删除默认值,因此您应该能够创建子类并对其进行模拟.这值得么?我最初的直觉反应是,这是一个巨大的代码味道.您的设计或测试都是错误的(t​​m).

如果你能提供一个真实的,具体的例子,你真的需要做这种测试,那么花一些时间思考一个解决方案是值得的.在那之前,我对"不要那样做"的纯粹学术回答感到满意.:)