1
public function thisMethod {
    $example = $this->methodReturnsObject()->this1->that2->there3->id;
    return $example;
}

PHPUnitでthisMethodをどのようにテストしますか?

明らかに、methodReturnsObject()が何かを返すという期待を書くことができます...しかし、何ですか?そのオブジェクトにはプロパティが関連付けられていますが、その値をどのようにモックしますか?

4

3 に答える 3

9

答えは「あなたはしません」です。ユニットテストでは、各クラスを個別にテストする必要があります。そこで実行しようとしているのは、ユニットテストではありません。私のコメントで言ったように、あなたはデメテルの法則を破っています。

  • 各ユニットは、他のユニットについての知識が限られている必要があります。現在のユニットに「密接に」関連しているユニットのみです。
  • 各ユニットは、その友達とのみ話す必要があります。見知らぬ人と話をしないでください。
  • 直接の友達とだけ話してください。

リファクタリングが必要なクラスが緊密に結合されています。ここでは、要点を説明するために最初にクラスを作成しましたが、通常は最初にテストを作成します。

チェーンの終わりから始めましょう:-

class there3
{
    private $id

    public function setId($id)
    {
        $this->id = $id;
    }

    public function getId()
    {
        return $this->id;
    }

}

それでは、ユニットテストを設定しましょう:-

class there3Test extends PHPUnit_Framework_TestCase
{
    public function testCanGetId()
    {
        $there3 = new there3();
        $there3->setId(3);
        $this->assertTrue($there3->getId() === 3);
    }
}

そのクラスは現在テストされているので、再度テストする必要はありません。次のものを見てみましょう:-

class this2
{
    public $there3;

    //To facilitate unit testing we inject the dependency so we can mock it
    public function __construct(there3 $there3)
    {
        $this->there3 = $there3;
    }

    public function getId()
    {
        return $this->there3->getId();
    }

}

そして今、ユニットテスト:-

class this2Test extends PHPUnit_Framework_TestCase
{
    public function testCanGetId()
    {
        $mockThere3 = $this->getMock('there3');
        $mockThere3->method('getId')
                   ->will($this->returnValue(3);

        $this2 = new this2($mockThere3);//We pass in the mock object instead of the real one
        $this->assertTrue($this2->getId() === 3);
    }
}

私のポイントをさらに説明するために、最後の例を1つ実行します。-

class this1
{
    private $this2;

    public function __construct(this2 $this2)//injecting again
    {
         $this->$this2 = $this2;
    }

    public function getId()
    {
        return $this->$this2->getId();
    }
}

そして、繰り返しますが、ユニットテスト:-

class this1Test extends PHPUnit_Framework_TestCase
{
    public function testCanGetId()
    {
        $mockThis2 = $this->getMock('this2');
        $mockThis2->method('getId')
                  ->will($this->returnValue(3);

        $this1 = new this1($mockThis2);//We pass in the mock object instead of the real one
        $this->assertTrue($this1->getId() === 3);
    }
}

うまくいけば、私があなたの例のすべてのオブジェクトを調べなくても、あなたはアイデアを得ることができます。

私がやったことは、クラスを互いに切り離すことです。彼らは依存しているオブジェクトについての知識しか持っておらず、そのオブジェクトが要求された情報をどのように取得するかは気にしません。

これで、idの呼び出しは次のようになります。-

public function getId()
{
    return $this->this1->getId();
}

返されるIDがthere2::idになるまでチェーンを上っていきます。$ this-> $ this1-> $ this2-> there3-> idのようなものを書く必要はなく、クラスを適切に単体テストできます。

ユニットテストの詳細については、PHPUnitのマニュアルを参照してください。

于 2012-09-21T19:48:10.700 に答える
2

PHPUnitでthisMethodをどのようにテストしますか?

  1. ユニットテストが3つ以上のネストされたパーツをモックするポイントに到達しないようにしてください
  2. オブジェクトのランダムバージョンを作成し、ランダムが同じであることを確認します

そのような:

<?php

// an opaque known
$random = rand();

// the results
$value = new stdClass();
$value->this1 = new stdClass();
$value->this1->this2 = new stdClass();
$value->this1->this2->there3 = new stdClass();
$value->this1->this2->there3->id = $random;

// somehow get the known value into the fixture
// not enough detail shown about $this->methodReturnsObject()
// to make a reasonable suggestion about it.


$this->assertEquals(
   $random, $this->fixture->thisMethod(),
   "Got a value from somewhere else"
);
于 2012-09-21T18:39:39.513 に答える
1

rrehbeinのメソッドを使用して、モックメソッドから戻り値を作成し、含まれているクラスとテスト対象のクラスの部分的なモックを作成しthisMethodますmethodReturnsObject。作成されたオブジェクトmethodReturnsObjectを返すためのモック。$value

Fooクラスに名前が付けられていると仮定すると、

function testThisMethod() {
    $foo = $this->getMock('Foo', array('methodReturnsObject'));
    $value = // create as rrehbein demonstrated
    $foo->expects($this->once())
        ->method('methodReturnsObject')
        ->will($this->returnValue($value));
    self::assertSame($value, $foo->thisMethod());
}
于 2012-09-21T19:35:57.043 に答える