PHPUnit测试返回对象属性的方法 [英] PHPUnit test a method that returns an objects property

查看:113
本文介绍了PHPUnit测试返回对象属性的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

您将如何在PHPUnit中测试thisMethod?

很明显,我可以写一个期望,methodReturnsObject()将返回一些东西……但是呢?该对象具有与之关联的属性,但是您怎么会模拟该值呢?

解决方案

答案是您不要".单元测试应该单独测试每个类,而您要尝试做的是没有单元测试.正如我在评论中说的那样,您违反了《德米特律法》 , >

  • 每个单位对其他单位的知识应该是有限的:只有与当前单位密切相关"的单位.
  • 每个单位只能与自己的朋友交谈;不要跟陌生人说话.
  • 仅与您的直属朋友交谈.

您那里紧密耦合了需要重构的类.我在这里首先编写了类以说明要点,但是通常我会首先编写测试.

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

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

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

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手册. /p>

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

How would you test thisMethod in PHPUnit?

Obviously I could write an expectation that methodReturnsObject() will return something... but what? That object has properties associated with it, but how would you even mock that value?

解决方案

The answer is "You don't". Unit testing should test each class in isolation, what you are trying to do there is not a unit test. As I said in my comment, you are breaking the Law of Demeter, which simply stated says

  • Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
  • Each unit should only talk to its friends; don't talk to strangers.
  • Only talk to your immediate friends.

You have tightly coupled classes there that need re-factoring. I have written the classes first here to illustrate the point, but I usually write the tests first.

Lets start with the end of the chain:-

class there3
{
    private $id

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

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

}

Now let's set up a unit test for it:-

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

That class is now tested, so we don't need to test it again. Now let's look at the next one:-

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

}

And now the unit test:-

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

We'll do one last example to further illustrate my point:-

class this1
{
    private $this2;

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

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

And, again, the unit test:-

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

Hopefully, you get the idea without me having to go through all the objects in your example.

What I have done is to de-couple the classes from each other. They only have knowledge of the object they depend on, they don't care how that object gets the information requested.

Now the call for id would look something like:-

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

Which will go up the chain until the id returned is there2::id. You never have to write something like $this->$this1->$this2->there3->id and you can unit test your classes properly.

For more information on unit testing see the PHPUnit manual.

这篇关于PHPUnit测试返回对象属性的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆