PHPUnit的测试返回一个对象属性的方法(PHPUnit test a method that r

2019-09-22 17:48发布

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

你将如何在PHPUnit的测试thisMethod?

很显然,我可以写一个期望,methodReturnsObject()返回的东西......但什么? 这个对象有与它相关联的属性,但你怎么会连嘲笑价值?

Answer 1:

答案是“你不会”。 单元测试应该在单独测试每个类,你正在尝试做的没有一个单元测试。 正如我在我的评论说,你打破了德米特法 ,它只是说明说

  • 每个单元有关于其他单位只有有限的知识:只有单位“密切”关系到当前的单元。
  • 每个单位应该只跟它的朋友; 不要和陌生人说话。
  • 只有跟你的朋友即时。

你已经紧耦合类有需要重新分解。 我已经写了第一类在这里说明这一点,但我通常先写测试。

让我们先从链的末端 -

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。 你再也不用写类似$此 - > $ this1 - > $ this2-> there3-> ID,您可以单位正确地测试类。

用于单元测试的更多信息请参见PHPUnit的手册 。



Answer 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"
);


Answer 3:

使用rrehbein的方法来建立从模拟方法的返回值,并创建一个部分模拟任何的类包含thisMethodmethodReturnsObject被测--the类。 模拟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());
}


文章来源: PHPUnit test a method that returns an objects property