public function thisMethod {
$example = $this->methodReturnsObject()->this1->that2->there3->id;
return $example;
}
您如何在PHPUnit中测试thisMethod?
显然我可以写一个期望,即methodReturnsObject()会返回一些内容......但是什么?该对象具有与之关联的属性,但您如何模拟该值呢?
答案 0 :(得分:5)
答案是“你没有”。单元测试应该单独测试每个类,你试图做的是没有单元测试。正如我在评论中所说,你打破了Law of Demeter,简单地说明了
你有紧密耦合的类需要重新分解。我先在这里编写了类来说明这一点,但我通常先写测试。
让我们从链的末尾开始: -
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 manual。
答案 1 :(得分:2)
你如何在PHPUnit中测试thisMethod,我要么:
如:
<?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"
);
答案 2 :(得分:1)
使用rrehbein的方法从mock方法构建返回值,并创建包含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());
}