0

I'm trying to create a test in PHPSpec for an function that calls a function on another object with differing parameters. So far, my attempts have caused several different errors so I'll outline what I have so far.

The most recent error:

- it should find all realm data
  method call:
    - fetch(LeagueOfData\Adapters\Request\RealmRequest:000000001212f67d000000001262e5c6 Object (
      'apiDefaults' => Array &0 (
          'region' => 'euw'
      )
      'format' => null
      'data' => null
      'query' => null
      'where' => Array &0
  ))
  on Double\AdapterInterface\P51 was not expected, expected calls were:
    fetch(exact(Double\RequestInterface\P50:000000001212f607000000001262e5c6 Object (
      'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)

The PHPSpec file:

class JsonRealmsSpec extends ObjectBehavior
{
    function let(AdapterInterface $adapter, LoggerInterface $logger, RequestInterface $request)
    {
        // fetch called with multiple request objects but we're not interested in the exact data it returns yet.
        $adapter->fetch($request)->willReturn(['test data']);
        $this->beConstructedWith($adapter, $logger);
    }

    function it_should_find_all_realm_data()
    {
        $this->findAll()->shouldReturnArrayOfRealms();
    }


    function getMatchers()
    {
        return [
            'returnArrayOfRealms' => function($realms) {
                foreach ($realms as $realms) {
                    if (!$realm instanceof Realm) {
                        return false;
                    }
                }
                return true;
            }
        ];
    }
}

And the actual function being tested:

class JsonRealms implements RealmService
{
    const REGIONS = ['euw', 'eune', 'na'];

    private $source;
    private $log;
    private $realms;

    public function __construct(AdapterInterface $adapter, LoggerInterface $log)
    {
        $this->source = $adapter;
        $this->log = $log;
    }

    public function findAll() : array
    {
        $this->realms = [];
        foreach (self::REGIONS as $region) {
            $request = new RealmRequest(['region' => $region]);
            $response = $this->source->fetch($request);
            $this->realms[] = new Realm($realm['cdn'], $realm['v'], $region);
        }
        return $this->realms;
    }
}

I'm sure I'm probably missing something really obvious but for the life of me I cannot see it right now.

Acaeris
  • 175
  • 2
  • 11
  • Problem here is not that you are calling the function multiple times in SUS (system under spec; your class). The problem is that you are creating it inside that class whereas @ spec level you are asserting that you expect a call with the collaborator (and it is not the same object (type) and has not the same values). Take a look to my [answer](http://stackoverflow.com/questions/42307939/how-to-get-property-from-stub-function-argument) for a similar question. – DonCallisto Mar 02 '17 at 14:13
  • Hi, I'm not certain I entirely understand your answer. The function I'm calling multiple times isn't what I'm testing. I'm merely mocking it. I'm testing if the findAll() function returns an array of Realm objects. This is from some refactoring where I've changed the function from fetching a single realm, to fetching all of them. I have solved the issue myself though and will add the answer. – Acaeris Mar 02 '17 at 14:54

1 Answers1

1

So it turns out I was missing something obvious, I was trying to solve it with a single mock call, as opposed to one for each case:

function let(AdapterInterface $adapter, LoggerInterface $logger) {
    $request = new RealmRequest(['region' => 'euw']);
    $adapter->fetch($request)->willReturn([
        'cdn' => 'http://test.url/euw',
        'v' => '7.4.3'
    ]);
    $request = new RealmRequest(['region' => 'eune']);
    $adapter->fetch($request)->willReturn([
        'cdn' => 'http://test.url/eune',
        'v' => '7.4.3'
    ]);
    $request = new RealmRequest(['region' => 'na']);
    $adapter->fetch($request)->willReturn([
        'cdn' => 'http://test.url/na',
        'v' => '7.4.3'
    ]);
}

This appropriately sets up the mock adapter so that we can test the service is correctly creating the Realm objects.

Acaeris
  • 175
  • 2
  • 11