【问题标题】:phpspec - method returns object instead of stringphpspec - 方法返回对象而不是字符串
【发布时间】:2014-07-31 00:51:39
【问题描述】:

我对 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;
    }

}

这是我的规范类的外观:

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

}

在运行 phpspec 后,我得到了这个错误:

warning: json_decode() expects parameter 1 to be string, object given in

我不知道如何解决这个问题。如果有人有线索,请帮忙。

【问题讨论】:

  • 警告很清楚,$child->getJsonQuery() 是一个对象,json_decode 需要字符串,看看类中是否有类似$child->getJsonQuery()->jsonString() 或类似的方法
  • 有:$child->getJsonQuery(),它被存根:$child->getJsonQuery()->shouldBeCalled()->willReturn($query);$child 是一个实体,而 jsonQuery 是其中的一个字段,所以当 $child->getJsonQuery() 被调用时,我认为它会返回字符串(因为我将它存根)。

标签: php symfony testing phpspec


【解决方案1】:

这是 PhpSpec 的常见绊脚石,声明:

   MyClass $child

表示 $child 的 Collaborator 对象将设置为与 MyClass 相同的接口。 当在 SUT(您正在测试的类)中调用 child->getJsonQuery() 时,它将返回一个 MethodProphecy 而不是您希望它返回的字符串。

你想说的是,你的 ArrayCollection 将包含 不是 $child 本身(它是一个 Collaborator 对象),而是collaborator 所包裹的真实对象。你这样做:

$returnCollection = new ArrayCollection(array($child->getWrappedObject()));

此外,您不应该同时使用(即是多余的)两者 shouldBeCalled() 和 willReturn() 在同一个 Collaborator 上,一个或 其他就足够了。如果您已指定协作者将 返回,很明显它将在 SUT 中调用。 shouldBeCalled() 应该用在测试的“断言”部分 为了确认协作者被调用了预期的 争论,或在正确的时间。

您的最终 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;
        }
    }

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

}

还有一行

$query = \json_decode($child->getJsonQuery(), true);

将在 $query 中生成一个关联数组,即 array('id' => 1) (这是 json_encode 的第二个 'true' 参数规定的),因此您希望 $someFetcher->getData()与后者一起调用,因此:

$someFetcher->getData(array('id' => 1))->shouldBeCalled();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-18
    • 2011-07-29
    • 2012-11-26
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多