php - 为什么 phpunit 不在模拟类中运行 __destruct() 以及如何强制运行它?

标签 php unit-testing mocking phpunit destructor

代码会解释一切:

<?php

class ATest extends PHPUnit_Framework_TestCase
{
    public function testDestructorOnOriginalClass() {
        $a = new A();                                             // It
        unset($a);                                                // works
        echo " great!";                                           // great!
        $this->expectOutputString('It works great!');
    }

    public function testDestructorOnMockedClass() {
        $a = $this->getMock('A', array('someNonExistingMethod')); // It
        unset($a);                                                // works
        echo " great!";                                           // great!
        $this->expectOutputString('It works great!');
    }
}

class A {
    public function __construct()
    {
        echo "It";
    }

    public function __destruct()
    {
        echo " works";
    }
}

和输出:

# phpunit ATest.php 
PHPUnit 3.7.13 by Sebastian Bergmann.

.F

Time: 0 seconds, Memory: 3.50Mb

There was 1 failure:

1) ATest::testDestructorOnMockedClass
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'It works great!'
+'It great! works'


FAILURES!
Tests: 2, Assertions: 2, Failures: 1.

正如您在第二个测试中所见,它以错误的顺序打印 works,可能是因为 phpunit 在某处存储了对 mock 的引用,并且 __destruct() 在结束时被调用测试... 好吧,我已经检查过 getMock() 方法,它确实有效地存储了对模拟对象 ($this->mockObjects[] = $mockObject;) 的引用阻止对象被破坏,因此永远不会调用 __destructor()

/**
 * Returns a mock object for the specified class.
 *
 * @param  string  $originalClassName
 * @param  array   $methods
 * @param  array   $arguments
 * @param  string  $mockClassName
 * @param  boolean $callOriginalConstructor
 * @param  boolean $callOriginalClone
 * @param  boolean $callAutoload
 * @param  boolean $cloneArguments
 * @return PHPUnit_Framework_MockObject_MockObject
 * @throws PHPUnit_Framework_Exception
 * @since  Method available since Release 3.0.0
 */
public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE)
{
    $mockObject = PHPUnit_Framework_MockObject_Generator::getMock(
      $originalClassName,
      $methods,
      $arguments,
      $mockClassName,
      $callOriginalConstructor,
      $callOriginalClone,
      $callAutoload,
      $cloneArguments
    );

    $this->mockObjects[] = $mockObject;

    return $mockObject;
}

所以问题是 - 有没有办法防止这种情况发生?在应该调用 __destruct() 时忽略它是我认为的错误限制。

最佳答案

问题是当你没有将任何值传递给“getMock”方法的第二个参数时,PHPUnit 将 stub 你正在模拟的类中的所有方法(包括“__destruct").

但是如果您至少指定了一个方法(它甚至可能是不存在的方法),PHPUnit 将只 stub 您在第二个参数中传递的这些方法。

所以如果你想保留所有方法,但你还想创建模拟,你应该这样做:

$mock = $this->getMock('A', array('someNonExistingMethod'));

如果您更改此行,您的测试应该会通过。

关于php - 为什么 phpunit 不在模拟类中运行 __destruct() 以及如何强制运行它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14858286/

相关文章:

java - android本地测试的数据文件

node.js - 如何使用 sinon/mocha 模拟 npm 模块

python - 如何对 __init__() 函数中调用的方法进行单元测试?

unit-testing - Groovy中的单元测试Abstract类

php - jquery 不适用于每个 href 元素

php - 在 EC2 上为 S3 托管网站运行 PHP 联系表单

Javascript变量传递带撇号的文本字符串,被 chop ?

Javascript 数组转换为 jQuery.post 的数据

java - 如何使用 JUnit 测试特定于操作系统的方法?

xml - 规范用于 JUnit XML 输出