Pergunta

Ainda estou iniciando no phpspec, mas geralmente encontro uma solução quando tenho dificuldade com alguma coisa, mas essa é difícil.

Tentei muitas abordagens diferentes e não encontrei uma solução.Estou usando o Symfony2.

Tenho uma classe que quero testar:

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

}

E aqui está como fica minha classe de especificações:

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

}

E depois de executar o phpspec estou recebendo este erro:

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

Não tenho ideia de como resolver esse problema.Se alguém tiver uma pista, por favor ajude.

Foi útil?

Solução

Este é um obstáculo comum com o PhpSpec, a declaração:

   MyClass $child

significa que um objeto Collaborator de $child será configurado com a mesma interface de MyClass.Quando child->getJsonQuery() for chamado no SUT (classe que você está testando), ele retornará um MétodoProfecia não a string que você espera que ela retorne.

O que você quer dizer é que seu ArrayCollection conterá não $child em si (que é um objeto Collaborator), mas o objeto real em torno do qual o colaborador está envolvido.Você faz assim:

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

Além disso, você não deve usar (ou seja,é supérfluo) que deve ser necessário () e willreng () no mesmo colaborador, um ou outro é suficiente.Se você especificou o que o colaborador retornará, fica claro que será chamado de súte.deve ser usado () deve ser usado na parte "assert" do teste para confirmar que o colaborador foi chamado com os argumentos esperados ou no momento certo.

Seu SUT e especificações finais devem ser parecidos com isto:

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

}

Além disso, a linha

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

Produzirá um array associado em $query, ou seja,array('id' => 1) (isto é o que o segundo argumento 'true' para json_encode estipula), portanto você esperaria que $someFetcher->getData() fosse chamado com o último, portanto:

$someFetcher->getData(array('id' => 1))->shouldBeCalled();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top