PHPUnit测试一个返回objects属性的方法

jst*_*ann 1 php phpunit zend-framework

public function thisMethod {
    $example = $this->methodReturnsObject()->this1->that2->there3->id;
    return $example;
}
Run Code Online (Sandbox Code Playgroud)

你会如何在PHPUnit中测试thisMethod?

显然我可以写一个期望,即methodReturnsObject()会返回一些东西......但是什么呢?该对象具有与之关联的属性,但您如何模拟该值?

vas*_*ite 7

答案是"你没有".单元测试应该单独测试每个类,你试图做的是没有单元测试.正如我在评论中所说,你违反了得墨忒耳法则,简单地说

  • 每个单位应该对其他单位的知识有限:只有与当前单位"密切"相关的单位.
  • 每个单位只应与其朋友交谈; 不要和陌生人说话.
  • 只与你的直接朋友交谈.

你有紧密耦合的类需要重新分解.我先在这里编写了类来说明这一点,但我通常先编写测试.

让我们从链的末尾开始: -

class there3
{
    private $id

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

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

}
Run Code Online (Sandbox Code Playgroud)

现在让我们为它设置一个单元测试: -

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

该类现在已经过测试,因此我们不需要再次测试它.现在让我们看看下一个: -

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();
    }

}
Run Code Online (Sandbox Code Playgroud)

现在单元测试: -

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我们将做最后一个例子来进一步说明我的观点: -

class this1
{
    private $this2;

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

    public function getId()
    {
        return $this->$this2->getId();
    }
}
Run Code Online (Sandbox Code Playgroud)

再次,单元测试: -

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望你能得到这个想法,而不必经历你的例子中的所有对象.

我所做的是将这些类彼此分离.他们只了解他们所依赖的对象,他们并不关心该对象如何获取所请求的信息.

现在对id的调用看起来像:

public function getId()
{
    return $this->this1->getId();
}
Run Code Online (Sandbox Code Playgroud)

哪个链上升,直到返回的id为there2 :: id.你永远不必写像$ this这样的东西 - > $ this1 - > $ this2-> there3-> id你可以正确地测试你的类.

有关单元测试的更多信息,请参阅PHPUnit手册.