phpunit避免模拟的构造函数参数

什么是避免phpunit不得不调用模拟对象的构造函数? 否则,我会需要一个模拟对象作为构造参数,另一个这样的api似乎是这样的:

getMock($className, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE) 

我没有得到它的工作。 它仍然抱怨构造函数的参数,即使$callOriginalConstructor设置为false。

我只有一个对象在构造函数中,它是一个dependency injection。 所以我不认为我有一个devise问题。

您可以使用getMockBuilder而不是getMock

 $mock = $this->getMockBuilder('class_name') ->disableOriginalConstructor() ->getMock(); 

有关详细信息,请参阅PHPUnit文档中的 “testing双精度”部分。

虽然你可以做到这一点,但不需要做得更好。 你可以重构你的代码,而不是需要注入的具体类(带有构造函数),而只依赖于一个接口。 这意味着你可以模拟或存根接口,而不必告诉PHPUnit修改构造函数的行为。

干得好:

  // Get a Mock Soap Client object to work with. $classToMock = 'SoapClient'; $methodsToMock = array('__getFunctions'); $mockConstructorParams = array('fake wsdl url', array()); $mockClassName = 'MyMockSoapClient'; $callMockConstructor = false; $mockSoapClient = $this->getMock($classToMock, $methodsToMock, $mockConstructorParams, $mockClassName, $callMockConstructor); 

作为一个附录,我想附加expects()调用我的模拟对象,然后调用构造函数。 在PHPUnit 3.7.14中,调用disableOriginalConstructor()时返回的对象实际上是一个对象。

 // Use a trick to create a new object of a class // without invoking its constructor. $object = unserialize( sprintf('O:%d:"%s":0:{}', strlen($className), $className) 

不幸的是,在PHP 5.4中有一个新的选项,他们没有使用:

ReflectionClass :: newInstanceWithoutConstructor

由于这是不可用的,我不得不手动反映类,然后调用构造函数。

 $mock = $this->getMockBuilder('class_name') ->disableOriginalConstructor() ->getMock(); $mock->expect($this->once()) ->method('functionCallFromConstructor') ->with($this->equalTo('someValue')); $reflectedClass = new ReflectionClass('class_name'); $constructor = $reflectedClass->getConstructor(); $constructor->invoke($mock); 

请注意,如果functionCallFromConstruct protected ,则必须使用setMethods()方法来模拟受保护的方法。 例:

  $mock->setMethods(array('functionCallFromConstructor')); 

setMethods()必须在expect()调用之前调用。 就我个人而言,在disableOriginalConstructor()但在getMock()之前,将其getMock()

也许你需要创build一个存根传入作为构造函数的参数。 那么你可以打破这一连串的模拟对象。

另外,你可以添加一个参数给getMock来防止调用默认的构造函数。

 $mock = $this->getMock(class_name, methods = array(), args = array(), mockClassName = '', callOriginalConstructor = FALSE); 

不过,我认为dave1010的答案看起来更好,这只是为了完整性。

PHPUnit被devise为在模拟对象上调用构造函数; 为了防止这种情况,你应该:

  1. 将一个模拟对象作为一个依赖项注入到您嘲笑的对象中
  2. 创build一个testing类来扩展您正在尝试调用的类,该类不调用父构造函数