wie*_*elo 0 php testing phpspec symfony
我在phpspec中仍然很新鲜,但通常我会在遇到困难时找到解决方案,但这个很难.
我尝试了很多不同的方法,但我还没有找到解决方案.我正在使用Symfony2.
我有一个我想测试的课程:
class MyClass
{
public function getDataForChildren(MyObject $object)
{
foreach ($object->getChildren() as $child) {
$query = \json_decode($child->getJsonQuery(), true);
$data = $this->someFetcher->getData($query);
$child->setData($data);
}
return $object;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我的spec类:
class MyClassSpec
{
function let(SomeFetcher $someFetcher)
{
$this->beConstructedWith($someFetcher);
}
function it_is_initializable()
{
$this->shouldHaveType('MyClass');
}
function it_should_get_data_for_children_and_return_object(
MyClass $object,
MyClass $child, // it means that MyClass has a self-reference to MyClass
$someFetcher
)
{
$query = '{"id":1}';
$returnCollection = new ArrayCollection(array($child));
$object->getChildren()->shouldBeCalled()->willReturn($returnCollection);
$child->getJsonQuery()->shouldBeCalled()->willReturn($query);
$someFetcher->getData($query)->shouldBeCalled();
$this->getDataForChildren($object);
}
}
Run Code Online (Sandbox Code Playgroud)
运行phpspec后,我收到此错误:
warning: json_decode() expects parameter 1 to be string, object given in
Run Code Online (Sandbox Code Playgroud)
我不知道如何解决这个问题.如果有人有线索,请帮忙.
小智 5
这是PhpSpec的一个常见绊脚石,声明:
MyClass $child
Run Code Online (Sandbox Code Playgroud)
表示将使用MyClass的相同接口设置$ child的Collaborator对象.当在SUT(您正在测试的类)中调用child-> getJsonQuery()时,它将返回MethodProphecy,而不是您希望它返回的字符串.
你想说的是你的ArrayCollection 不包含$ child本身(它是一个Collaborator对象),而是包含协作者的真实对象.你这样做:
$returnCollection = new ArrayCollection(array($child->getWrappedObject()));
Run Code Online (Sandbox Code Playgroud)
此外,你不应该在同一个协作者上使用(即多余的)shouldBeCalled()和willReturn(),其中一个就足够了.如果你已经指定了合作者将返回的内容,很明显它将在SUT中被调用.shouldBeCalled()应该用在测试的"assert"部分,以确认Collaborator是用预期的参数调用的,或者是在正确的时间调用的.
您的最终SUT和规格应如下所示:
class MyClass
{
/**
* @var SomeFetcher
*/
private $someFetcher;
public function getDataForChildren(MyObject $object)
{
foreach ($object->getChildren() as $child) {
$query = \json_decode($child->getJsonQuery(), true);
$data = $this->someFetcher->getData($query);
$child->setData($data);
}
return $object;
}
public function getJsonQuery()
{
}
public function setData()
{
}
public function __construct(SomeFetcher $someFetcher)
{
$this->someFetcher = $someFetcher;
}
}
Run Code Online (Sandbox Code Playgroud)
class MyClassSpec extends ObjectBehavior
{
function let(SomeFetcher $someFetcher)
{
$this->beConstructedWith($someFetcher);
}
function it_should_get_data_for_children_and_return_object(
MyObject $object,
MyClass $child, // it means that MyClass has a self-reference to MyClass
SomeFetcher $someFetcher
)
{
$query = '{"id":1}';
$returnCollection = new ArrayCollection(array($child->getWrappedObject()));
$object->getChildren()->willReturn($returnCollection);
$child->getJsonQuery()->willReturn($query);
$child->setData(Argument::any())->shouldBeCalled();
$someFetcher->getData(array('id' => 1))->shouldBeCalled();
$this->getDataForChildren($object);
}
}
Run Code Online (Sandbox Code Playgroud)
还有,行
$query = \json_decode($child->getJsonQuery(), true);
Run Code Online (Sandbox Code Playgroud)
将在$ query中生成一个关联的数组,即array('id'=> 1)(这是json_encode规定的第二个'true'参数),因此你希望调用$ someFetcher-> getData()后者因此:
$someFetcher->getData(array('id' => 1))->shouldBeCalled();
Run Code Online (Sandbox Code Playgroud)