2010-06-20 89 views
14

我正在为使用mock调用另一个类的方法的类方法编写单元测试,只有需要调用的方法声明为final,所以PHPUnit无法嘲笑它。我可以采取不同的方法吗?声明为“final”的PHPUnit存根类方法

例如:

类被嘲笑

class Class_To_Mock 
{ 
    final public function needsToBeCalled($options) 
    { 
     ... 
    } 
} 

我的测试用例

class MyTest extends PHPUnit_Framework_TestCase 
{ 
    public function testDoSomething() 
    { 
     $mock = $this->getMock('Class_To_Mock', array('needsToBeCalled')); 
     $mock->expects($this->once()) 
      ->method('needsToBeCalled') 
      ->with($this->equalTo(array('option')); 
    } 
} 

编辑:和如果使用由Mike乙方提供的解决方案,您有一个setter/getter为你嘲笑的对象进行类型检查(以确保将正确的对象传递给setter),哟你需要嘲笑你正在测试的类的吸气剂,并让它返回其他模拟。

例如:

类被模拟

class Class_To_Mock 
{ 
    final public function needsToBeCalled($options) 
    { 
     ... 
    } 
} 

模拟

class Class_To_MockMock 
{ 
    public function needsToBeCalled($options) 
    { 
     ... 
    } 
} 

类待测试

class Class_To_Be_Tested 
{ 
    public function setClassToMock(Class_To_Mock $classToMock) 
    { 
     ... 
    } 

    public function getClassToMock() 
    { 
     ... 
    } 

    public function doSomething() 
    { 
     $this->getClassToMock() 
      ->needsToBeCalled(array('option')); 
    } 
} 

我的测试用例

class MyTest extends PHPUnit_Framework_TestCase 
{ 
    public function testDoSomething() 
    { 
     $classToTest = $this->getMock('Class_To_Be_Tested', array('getClassToMock')); 

     $mock = $this->getMock('Class_To_MockMock', array('needsToBeCalled')); 

     $classToTest->expects($this->any()) 
        ->method('getClassToMock') 
        ->will($this->returnValue($mock)); 

     $mock->expects($this->once()) 
      ->method('needsToBeCalled') 
      ->with($this->equalTo(array('option')); 

     $classToTest->doSomething(); 
    } 
} 

回答

14

我不认为PHPUnit支持最终方法的stubbing/mocking。您可能需要创建自己的存根针对这一情况,并做一些伸展挂羊头卖狗肉:下Chapter 11. Test Doubles

限制

class myTestClassMock { 
    public function needsToBeCalled() { 
    $foo = new Class_To_Mock(); 
    $result = $foo->needsToBeCalled(); 
    return array('option'); 
    } 
} 

PHPUnit的手册中找到此请注意,最后,私有和静态方法不能被扼杀或嘲弄。它们被PHPUnit的测试双重功能忽略,并保留它们的原始行为。

+1

啊,错过了在手册中,由于 – 2010-06-20 16:31:09

+0

有一个额外的步骤,你需要的,如果这个类你重新测试依赖于一个getter/setter,它为被嘲笑的类/方法进行类型检查。我将其添加到原始帖子中。 – 2010-06-20 17:07:43

+0

@rr请考虑将其添加为答案,而不是将解决方案置于问题中。 – BartoszKP 2013-11-14 13:04:39

4

我今天偶然发现了这个问题。另一种方法是模拟类实现的接口,因为它实现了一个接口,并将接口用作类型提示。

例如,假设有问题的问题,你可以创建一个接口,按如下方式使用它:

interface Interface_To_Mock 
{ 
    function needsToBeCalled($options); 
} 

class Class_To_Mock implements Interface_To_Mock 
{ 
    final public function needsToBeCalled($options) 
    { 
     ... 
    } 

} 

class Class_To_Be_Tested 
{ 
    public function setClassToMock(Interface_To_Mock $classToMock) 
    { 
     ... 
    } 

    ... 
} 

class MyTest extends PHPUnit_Framework_TestCase 
{ 
    public function testDoSomething() 
    { 
     $mock = $this->getMock('Interface_To_Mock', array('needsToBeCalled')); 
     ... 
    } 
}