phpunit避免使用mock的构造函数参数

83 php phpunit unit-testing

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

getMock($className, $methods = array(), array $arguments = array(),
        $mockClassName = '', $callOriginalConstructor = TRUE,
        $callOriginalClone = TRUE, $callAutoload = TRUE)
Run Code Online (Sandbox Code Playgroud)

我不懂它.它仍然抱怨构造函数参数,即使$callOriginalConstructor设置为false.

我只在构造函数中有一个对象,它是一个依赖注入.所以我认为那里没有设计问题.

dav*_*010 135

您可以使用getMockBuilder而不仅仅是getMock:

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();
Run Code Online (Sandbox Code Playgroud)

参见节"测试双打"PHPUnit的文档的详细信息.

虽然你可以这样做,但不需要这样做要好得多.您可以重构代码,而不是需要注入的具体类(使用构造函数),您只依赖于接口.这意味着您可以模拟或存根接口,而无需告诉PHPUnit修改构造函数行为.


Mat*_*don 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);
Run Code Online (Sandbox Code Playgroud)


Wes*_*ves 7

这个问题有点老了,但是对于新来的访问者,可以使用createMock方法(之前createTestDouble在v5.4.0中调用并引入)。

$mock = $this->createMock($className);
Run Code Online (Sandbox Code Playgroud)

正如您在下面从PHPUnit\Framework\TestCase类 (in phpunit/src/framework/TestCase.php)中提取的代码中看到的那样,它基本上会创建一个模拟对象,而无需调用原始构造函数

/** PHPUnit\Framework\TestCase::createMock method */
protected function createMock(string $originalClassName): MockObject
{
    return $this->getMockBuilder($originalClassName)
                ->disableOriginalConstructor()
                ->disableOriginalClone()
                ->disableArgumentCloning()
                ->disallowMockingUnknownTypes()
                ->getMock();
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ber 5

作为附录,我想将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)
Run Code Online (Sandbox Code Playgroud)

不幸的是,在 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);
Run Code Online (Sandbox Code Playgroud)

请注意,如果functionCallFromConstructprotected,您必须特别使用setMethods()以便模拟受保护的方法。例子:

    $mock->setMethods(array('functionCallFromConstructor'));
Run Code Online (Sandbox Code Playgroud)

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


Gle*_*oss 1

也许您需要创建一个存根作为构造函数参数传入。然后你可以打破模拟对象链。