Phpspec - Metodo restituisce l'oggetto invece della stringa
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.
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();
.