6

コードはすべてを説明します:

<?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.

2番目のテストでわかるようにworks、おそらくphpunitがモックへの参照をどこかに格納__destruct()し、テストの最後に呼び出されるため、間違った順序で出力されます... OKすでに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()いつ呼ばれるべきかを無視するのは悪い制限だと思います。

4

3 に答える 3

2

問題は、" " メソッドの 2 番目のパラメーターに値を渡さない場合getMock、PHPUnit はモックしているクラスのすべてのメソッド (" __destruct" を含む) をスタブ化することです。

ただし、少なくとも 1 つのメソッドを指定すると (存在しないメソッドの場合もあります)、PHPUnit は 2 番目の引数に渡したメソッドのみをスタブ化します。

したがって、すべてのメソッドを保持したいが、モックも作成したい場合は、次のようにする必要があります。

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

この行を変更すると、テストに合格するはずです。

于 2013-02-13T17:47:55.157 に答える
1

ローカル変数の設定を解除しているだけです-オブジェクト自体を破壊していません。

オブジェクトは、PHPUnit 自体にも保持されます。そのため、まだ参照が存在するため、あなたunset()__destruct().

したがって、現在の動作を変更することはできません。phpunit issue tracker でバグを開きます。

于 2013-02-13T17:26:03.420 に答える