避免phpunit必须为模拟对象调用构造函数的方法是什么?否则我需要一个模拟对象作为构造函数参数,另一个需要它等.api似乎是这样的:
getMock($className, $methods = array(), array $arguments = array(),
$mockClassName = '', $callOriginalConstructor = TRUE,
$callOriginalClone = TRUE, $callAutoload = TRUE)
我没有让它发挥作用。它仍然会抱怨构造函数参数,即使$callOriginalConstructor
设置为false。
我在构造函数中只有一个对象,它是一个依赖注入。所以我认为那里没有设计问题。
答案 0 :(得分:135)
您可以使用getMockBuilder
代替getMock
:
$mock = $this->getMockBuilder('class_name')
->disableOriginalConstructor()
->getMock();
有关详细信息,请参阅"Test Doubles"中PHPUnit's documentation部分。
虽然你可以做到这一点,但不需要做得更好。您可以重构代码,而不是需要注入的具体类(使用构造函数),您只依赖于接口。这意味着您可以模拟或存根接口,而无需告诉PHPUnit修改构造函数行为。
答案 1 :(得分:42)
你走了:
// 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);
答案 2 :(得分:3)
作为附录,我想将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()
来电之前调用{p> expect()
。就个人而言,我在disableOriginalConstructor()
之后但在getMock()
之前将其链接起来。
答案 3 :(得分:1)
也许你需要创建一个存根作为构造函数参数传入。然后你可以打破那个模拟对象链。
答案 4 :(得分:1)
或者,您可以向getMock添加参数,以防止调用默认构造函数。
$mock = $this->getMock(class_name, methods = array(), args = array(),
mockClassName = '', callOriginalConstructor = FALSE);
不过,我认为dave1010的答案看起来更好,这只是为了完整。
答案 5 :(得分:1)
这个问题有点老了,但是对于新来访者,您可以使用createMock
方法(以前称为createTestDouble
,在v5.4.0中引入)来完成。
$mock = $this->createMock($className);
如下面从PHPUnit\Framework\TestCase
类(在phpunit/src/framework/TestCase.php
中提取的代码中看到的),它基本上将创建一个模拟对象,而无需调用原始构造函数。 / p>
/** PHPUnit\Framework\TestCase::createMock method */
protected function createMock(string $originalClassName): MockObject
{
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
}
答案 6 :(得分:0)
PHPUnit旨在调用模拟对象上的构造函数;要防止这种情况,你应该: