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

在...创建的问题 Wed, Apr 20, 2011 12:00 AM

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

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

我没有让它发挥作用。它仍然抱怨构造函数参数,即使$callOriginalConstructor设置为false。

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

    
80
6答案                              6 跨度>                         

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

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

请参阅”测试双打“部分/phpunit.de/manual">PHPUnit的文档了解详情。

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

    
135
2015-04-29 13:02:25Z
  1. 这对我很有用。不过应该是例10.3。我试图编辑帖子,但是因为编辑太短而踢了回来。
    2012-05-31 13:34:59Z
  2. 谢谢@Lytithwyn。更新了答案。
    2012-05-31 15:14:32Z
  3. 也适合我。谢谢!
    2012-06-11 09:26:40Z
  4. 醇>

你走了:

 
    // 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);
    
42
2012-11-09 05:56:42Z
  1. 这似乎几乎是我想要的。我想调用getMock,只调用类和$callMockConstructor。怎么样?像这样:$this-> getMock($classToMock,$callMockConstructor)。我唯一能想到的是进入PHPUnit的源代码并将其更改为default = false。
    2010-04-16 18:53:39Z
  2. 我在testcase.php中将默认值更改为false。你会认为它默认设置为false。模拟构造函数似乎很奇怪
    2010-04-16 19:15:56Z
  3. OBTW,谢谢!
    2010-04-16 19:22:02Z
  4. 优秀的答案。正是我在寻找
    2013-01-18 00:19:02Z
  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)

不幸的是,在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);

注意,如果functionCallFromConstructprotected,你必须具体使用setMethods()以便模拟受保护的方法。例如:

 
    $mock->setMethods(array('functionCallFromConstructor'));
setMethods()通话之前必须先拨打expect()。就个人而言,我在disableOriginalConstructor()之后但在getMock()之前将其链接起来。     
3
2013-03-28 01:18:47Z

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

    
1
2008-12-01 22:30:16Z
  1. 请你分享更多信息
    2017-05-16 07:40:32Z
  2. 醇>

或者你可以在 getMock 以防止调用默认构造函数。

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

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

    
1
2018-10-29 13:59:12Z

PHPUnit旨在调用模拟对象上的构造函数;要防止这种情况,你应该:

  1. 将模拟对象作为依赖项注入到您无法模拟的对象中
  2. 创建一个测试类,扩展您尝试调用的类,而不调用父构造函数
0
2008-12-08 21:08:18Z
来源放置 这里