Domanda

Sono ancora fresco in Phpspec, ma di solito sto trovando una soluzione quando faccio lottare con qualcosa, ma questo è difficile.

Ho provato molti approcci diversi e non ho trovato una soluzione.Sto usando symfony2.

Ho una classe che voglio testare:

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

}
.

Ed ecco come guarda la mia classe di specifiche:

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 dopo l'esecuzione di phpspec sto ricevendo questo errore:

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

Non ho idea di come risolvere questo problema.Se qualcuno ha un indizio, per favore aiuto.

È stato utile?

Soluzione

Questo è un comune blocco con phpspec, la dichiarazione:

   MyClass $child
.

significa che un oggetto collaboratore di $ bambino sarà impostato con la stessa interfaccia di myclass. Quando Child-> GetJsonQuery () è chiamato in Sut (Classe che stai testando), restituirà un metodo Prophecy non la stringa che ti aspetti di tornare.

Cosa vuoi dire è che la tua ArrayCollection conterrà non $ bambino stesso (che è un oggetto collaboratore), ma il vero oggetto che il collaboratore è avvolto. Lo fai così:

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

.

Inoltre, non dovresti usare (I.e. è superfluo) entrambi dovrebbe essere necessario () e willtreturn () sullo stesso collaboratore, uno o il altro è sufficiente. Se hai specificato ciò che lo farà il collatraglio Ritorna, è chiaro che sarà chiamato con il sut. dovrebbe essere necessario () dovrebbe essere usato nella parte "Assert" del test in per confermare che il collaboratore è stato chiamato con il previsto argomenti o al momento giusto.

La tua utum finale e le specifiche dovrebbe essere simile a questo:

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

}
.

Anche, la linea

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

produrrà un array associato in $ query, cioè array ('id'=> 1) (questo è qual è il secondo argomento 'true' a json_code stabilisce), quindi ti aspetteresti $ Someftcher-> GetData () a Essere chiamato con quest'ultimo, quindi:

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top