Can phpunit nativly test a jsonp API

72 views Asked by At

I had an API that I wrote tests for with phpunit (It is in Laravel if that makes any difference)

We had to change this API to work via JSONP, which was not that tricky.

However obviously all the tests are broken. They expect json packets and are getting jsonp.

I can't find any libraries or support for testing jsonp apis. It doesn't sound too tricky to add a callback to the request and parse the response, so am am curious as to why this has not been done.

I'm happy to write my own code to do this, but figured there must be something that does it already.

2

There are 2 answers

0
DanielM On

I ran into a similar problem when I started working on my Api framework. Part of the answer here is not to use Unit tests. These should only test a single method. Where dependencies on other classes exist, you should mock them. Unit tests on those classes will let you know if they work.

For testing sending data to a server and what the actual result is, I'd suggest Behat. You can use this with Selenium which will actually allow you to run the JS, however this is a) difficult to set up, b) slow.

As an alternative, I used Guzzle, and this is my Feature Context:

https://gist.github.com/Gisleburt/54e4a3b70b665c8ee053

This isn't a perfect answer to your problem as you would need to trim the response for PHP to be able to read the JSON, but it will be much faster than using Selenium.

0
Jeremy French On

It can't do it natively. But the following code in my apps TestCase.php does the trick.

// Method for the jsonp tests, wraps call and abstracts out the jsonp.
public function jsonpCall($path, $parameters = [], $files = [], $server = []) {
  $callback_name = 'test_callback';
  $parameters['callback'] = $callback_name;
  $response = $this->call('GET', $path, $parameters, $files, $server);
  $response_content = $this->client->getResponse()->getContent();
  if (($callback_start = strpos($response_content, $callback_name)) !== false) {
    $substr_start = $callback_start + strlen($callback_name) + 1;
    $substr_len = strrpos($response_content,')') - $substr_start;
    $encoded_json = substr($response_content, $substr_start, $substr_len);
    $json = json_decode($encoded_json, true);
    $this->assertNotNull($json, 'Json returned could not be decoded');
  return $json;
  }
  else {
    $this->fail('No callback found in jsonP response');
  }
}