0

私はまだ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

この問題を解決する方法がわかりません。誰か手がかりがある場合は、助けてください。

4

1 に答える 1

5

これは、次の宣言である PhpSpec の一般的な障害です。

   MyClass $child

$child の Collaborator オブジェクトが MyClass の同じインターフェイスでセットアップされることを意味します。child->getJsonQuery() が SUT (テストしているクラス) で呼び出されると、返されると予想される文字列ではなくMethodProphecyが返されます。

あなたが言いたいのは、ArrayCollection には$ child 自体 (Collaborator オブジェクト) ではなく、コラボレーターがラップされている実際のオブジェクトが含まれるということです。次のようにします。

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

さらに、同じ Collaborator で shouldBeCalled() と willReturn() の両方を使用しないでください (つまり、不要です)。どちらか一方で十分です。コラボレータが返すものを指定した場合、それが SUT 内で呼び出されることは明らかです。予想される引数で、または適切なタイミングで Collaborator が呼び出されたことを確認するために、テストの「アサート」部分で 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 の 2 番目の 'true' 引数が規定するものです) を生成します。後者、したがって:

$someFetcher->getData(array('id' => 1))->shouldBeCalled();
于 2015-01-01T14:58:48.560 に答える