坚持编写PHPUnit getMock单元测试

时间:2014-03-09 05:57:57

标签: php unit-testing phpunit

我认为单元测试非常生疏。

我在Registration.php中有以下功能:

protected function _showModal($request) {
  if (Store::isUserSupported()) { 
    return false; 
  }
  return true;
}

我开始编写以下测试,但我知道我缺少一些关键项目:

public function testUserSupported() {

$mockStore = $this->getMockClass('Store', array('isUserSupported'));

$mockStore::staticExpects($this->once()) 
->method('isUserSupported')
            ->will($this->returnValue(true));

$mockStore::isUserSupported();

$plugin = $this->getMockBuilder('Registration')
            ->setMethods(array('_showModal'))
            ->disableOriginalConstructor()
            ->getMock();

$plugin = $this->getPublicClass($plugin);

$plugin->expects($this->once())
            ->method('_showTermsModal')
            ->will($this->returnValue(true));

}

$ mockStore部分被调用,但不知道如何将它绑定到我的$ plugin调用..我想编写一个测试来模拟Store :: isUserSupported()在showModal函数中返回true。有任何建议吗?

1 个答案:

答案 0 :(得分:2)

您应该避免代码中的静态调用,因为它们会使您的代码耦合在一起,难以更改并且难以维护。这也使得测试变得更加困难,因为你在这里受苦。

而不是静态调用,传递工作所需的协作者。在您的代码示例中,您要测试的类将作为Store类的参数接收,而不是静态调用它。

通过执行此更改,您现在可以为Store类的方法isUserSupported()创建一个模拟,并将模拟传递给正在测试的对象,这将有效地使用模拟对象。

$mockStore = $this->getMock('Store', array('isUserSupported'));

$mockStore->expects($this->once())
    ->method('isUserSupported')
    ->will($this->returnValue(true));

$object_under_test = new Registration( $mockStore );
$object_under_test->showModal($request); // Only in case showModal is public, otherwise call public method

如果只有该方法需要Store类,并且您不想在构造函数中将其作为依赖项传递,则可以在方法本身上传递它。

$mockStore = $this->getMock('Store', array('isUserSupported'));

$mockStore->expects($this->once())
    ->method('isUserSupported')
    ->will($this->returnValue(true));

$object_under_test = new Registration();
$object_under_test->showModal($mockStore, $request); // Only in case showModal is public, otherwise call public method

此外,您不应该测试类的protected / private方法,因为它们是您的测试不需要了解的低级实现细节。您应该只在测试中调用公共方法。否则,测试将与实际实现非常相关,如果您重构代码,您很可能也必须更改测试。