2010-07-21 117 views
17

我试图配置PHPUnit中一个模拟对象返回不同属性的值(即正在使用的功能__get访问)的PHPUnit - 创建模拟对象充当存根属性

实施例:

class OriginalObject { 
public function __get($name){ 
switch($name) 
case "ParameterA": 
    return "ValueA"; 
case "ParameterB": 
    return "ValueB"; 
} 
} 

我想用这个来嘲笑:

$mockObject = $this->getMock("OrigionalObject"); 

$mockObject ->expects($this->once()) 
    ->method('__get') 
    ->with($this->equalTo('ParameterA')) 
    ->will($this->returnValue("ValueA")); 

$mockObject ->expects($this->once()) 
    ->method('__get') 
    ->with($this->equalTo('ParameterB')) 
    ->will($this->returnValue("ValueB")); 

但这种可怕的失败:-(

+1

是错别字(“原始”,而不是“原始”,缺少的值a和valueB收盘行情)在模拟代码是你的实际代码的一部分,还是抄写错误? – Phil 2010-07-29 12:59:46

+1

大声笑感谢菲尔(指出我的阅读障碍) 错字(现在修改)只是在示例代码 - 显然这不是正在执行的实际代码 – Tim 2010-07-30 05:56:18

回答

9

我还没有尝试过嘲讽__get还,但也许这将工作:

// getMock() is deprecated 
// $mockObject = $this->getMock("OrigionalObject"); 
$mockObject = $this->createMock("OrigionalObject"); 

$mockObject->expects($this->at(0)) 
    ->method('__get') 
    ->with($this->equalTo('ParameterA')) 
    ->will($this->returnValue('ValueA')); 

$mockObject->expects($this->at(1)) 
    ->method('__get') 
    ->with($this->equalTo('ParameterB')) 
    ->will($this->returnValue('ValueB')); 

我已经使用$这个 - >在()在测试和它的作品(但不是最佳解决方案) 。我是从这个胎面:

How can I get PHPUnit MockObjects to return different values based on a parameter?

+0

哎koen $ this-> at()适合我 - 谢谢;-) 为什么你不认为这是一个最佳的解决方案? – Tim 2010-07-30 05:58:15

+1

这不是真正的可扩展性,测试很难阅读。如果你给它一个好名字,回调可能会更容易阅读。但首先,我会考虑重构__get。 – koen 2010-07-30 06:41:01

+0

另外,你正在测试状态(有些人认为是不好的做法),甚至更多的是私人状态(许多人认为这是不好的做法)。当然,有些聪明的人并没有看到问题,你可能就是其中之一。 – koen 2010-07-30 06:44:50

4

这应该工作:

class Test extends \PHPUnit_Framework_TestCase { 
... 
    function testSomething() { 
     $mockObject = $this->getMock("OrigionalObject"); 

     $mockObject 
       ->expects($this->any()) 
       ->method('__get') 
       ->will($this->returnCallback('myMockGetter')); 
     ... 
    } 
... 
} 

function myMockGetter($classPropertyName) { 
    switch($classPropertyName) { 
     case 'ParameterA': 
      return 'ValueA'; 

     case 'ParameterB': 
      return 'ValueB'; 
    } 
} 
... ... 
+0

我认为我的解决方案比koen更优化,但他在评论中提出了一些重要的观点。我认为一种可能的解决方案是创建一个测试类,而不是使用模拟对象。这通常用于诸如HTTP适配器之类的东西。 – 2011-09-02 01:56:44