14

PHPUnitを使用してモッククラスを作成し、そのクラス名を使用しての新しいインスタンスを作成する方法はありますか?

2つのメソッドを定義するインターフェースがあります。何かのようなもの:

interface FooInterface {
    function getA();
    function getB();
}

次に、クラス名を受け入れ、そのクラスのインスタンスを作成し、それが期待するもののインスタンスであるかどうかを確認し(FooInterface)、そのクラスの2つのメソッドを呼び出して情報を取得する別のクラスがあります。

class FooInfo {
    protected $a;
    protected $b;

    public function __construct($fooClass) {
        $foo = new $fooClass;

        if (!($foo instanceof FooInterface)) {
            throw new \Exception();
        }

        $this->a = $foo->getA();
        $this->b = $foo->getB();
    }
}

オブジェクトをうまくモックする方法を知っています。問題は、このクラスはオブジェクトではなくクラス名を受け入れるため(必要に応じて、指定されたクラスのインスタンスを作成するManagerの一部です)、通常のモックオブジェクトを使用できないことです。

モックオブジェクトを作成して、そのクラス名を使用しようとしました。オブジェクトをうまく作成しているようで、私がモックアウトした機能もあるようです。ただし、後で設定したwill($ this-> returnValue('myValue'))の部分には従わないようです。

public function testConstruct()
{
    $foo = $this->getMockForAbstractClass('Foo', array('getA', 'getB'));
    $foo->expects($this->any())->method->('getA')->will($this->returnValue('a'));
    $foo->expects($this->any())->method->('getB')->will($this->returnValue('b'));

    $copyClass = get_class($foo);
    $copy = new $copyClass();

    // Passes
    $this->assertTrue(method_exists($copy, 'getA');

    // Fails, $copy->getA() returns null.
    $this->assertEquals($copy->getA(), $foo->getA());
}

したがって、モックされた関数はありますが、すべてnullを返します。

何か案は?

4

2 に答える 2

14

クラスのコンストラクターでキーワードを使用することはnew、柔軟なユースケースを考えても、今経験している理由から、かなり悪い習慣です。

クラスは常に挿入されたクラス名の実際のインスタンスを作成するため、作成したモックは使用されないため、テストは機能しません。

そうは言っても、あなたがやりたいことは、padraicの優れたモックライブラリの嘲笑で行うことができます!必要なのは「インスタンスモック」です。

$mock = \Mockery::mock('overload:MyNamespace\MyClass');

インスタンス化されるとすぐに、実際のオブジェクトに転送されるモックに対する期待を定義できます。

嘲笑をphpUnitと統合するのは簡単で、プロジェクトのreadmeで詳しく説明されています。

そしてところで。各単体テストは、最適には1つのアサーションのみを作成する必要があります。

于 2013-01-31T11:21:10.977 に答える
0

メソッドはgetAgetB何を返すかを指定していないため、nullを返します。$fooいくつかのメソッドを呼び出すことによって、抽象に対してそれを指定しました。それを回避する方法はありません。

関数をテストするのは(不可能ではないにしても)難しいので、コード自体を書き直します。コンストラクターがクラス名ではなくクラスインスタンスを必要とする場合、テストは簡単です。文字列も受け入れる必要がある場合は、数行を記述して文字列入力を確認し、文字列が提供されている場合はクラスを作成できます。

于 2013-01-31T07:13:15.800 に答える