code prettify

Sunday 27 March 2016

Testing APIs in CodeIgniter 2.x using phpunit and Guzzle Http client

Sometimes we have apis implemented in our application and there are different levels at which these can be tested.

1. Unit tested at model level to check the logic is working fine
2. Tested at API call level to ascertain whether all the apis as expected are working and are returning data as expected.


Today, we will be learning how to test APIs in CodeIgniter 2.x version using phpunit and Guzzle Http client.

Basically Guzzle Http client is a client used to make http client requests.

Ref: https://github.com/guzzle/guzzle

"Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services."

We will basically be creating an API for a blog so as to get blog posts and add blog post. When testing APIs, we are basically testing the output format, expected fields in the output and their data type and value if needed.

Sample code can be found at git repository here: https://github.com/satejkumar/CodeIgniter_API_Testing

We are using composer to install the dependencies: phpunit and Guzzle http client.

So download the latest CodeIgniter 2.x version and create a composer.json file with the following content:

{
    "require": {
        "guzzlehttp/guzzle": "^6.1",
        "phpunit/phpunit": "*",
        "phpunit/php-invoker": "*",
        "phpunit/dbunit": "*"
    }
}

and then install the dependencies using the below command:

$ composer install

Then we create our test file inside application/tests/ folder called PostsTest.php

All the dependencies are included by the autoload file.

require('../../vendor/autoload.php');

Before doing each test case, we setup the Guzzle Http client and set the base uri of the API request as below inside setUp() function which is called before each test function call.

protected function setUp()
{
        $this->client = new GuzzleHttp\Client([
            'base_uri' => 'http://localhost/'
        ]);
}

One function is to test get post API request, so we are making a get request to url http://localhost/posts/index/1 to get the first post and are expecting a json content and the json content should have some fields and should have an id value of 1.

public function testGet_ValidInput_PostObject()
{
        $response = $this->client->get('posts/index/1');
        $this->assertEquals(200, $response->getStatusCode());

        $data = json_decode($response->getBody(), true);

        $this->assertArrayHasKey('id', $data);
        $this->assertArrayHasKey('title', $data);
        $this->assertArrayHasKey('content', $data);
        $this->assertArrayHasKey('author_id', $data);
        $this->assertArrayHasKey('emails_sent', $data);
        $this->assertArrayHasKey('created_at', $data);
        $this->assertArrayHasKey('updated_at', $data);
        $this->assertEquals(1, $data['id']);
}

So we are using assertArrayHasKey() function to check if a particular field is present in the data set and assertEquals() to check for value.

Another function is to test POST request to create a new blog post.

public function testPost_NewBlog_Post()
{
        $response = $this->client->post('posts/index', [
            'form_params' => [
                'title' => 'My Random Post',
                'content' => 'Content',
                'author_id' => 1
            ]
        ]);

        $this->assertEquals(200, $response->getStatusCode());
        $data = json_decode($response->getBody(), true);
        $this->assertGreaterThanOrEqual(1, $data['id']);
}

In the above function we are creating a post request to the url http://localhost/posts/index with post parameters and are then expecting a 200 status code output and a json content with a field "id" which should have an integer value greater than or equal to 1.

Now that we are done with the tests, we can run them from the project root directory using below command:

$ ./vendor/bin/phpunit application/tests/

Basically phpunit and Guzzle Http client help us in making requests and verify responses thus enabling us to test APIs.

Ref: https://ole.michelsen.dk/blog/testing-your-api-with-phpunit.html
Excerpt: "Remember it's just as important to test failing/edge cases as testing when things go well. Also you should run these tests against an isolated testing environment if they modify your data."

5 comments:

  1. Nice one . Will implement soon in my project. Thanks Satej.

    ReplyDelete
    Replies
    1. Thanks Lakin. Good to know. Would like to see it when you are done :)

      Delete
  2. I prefer using PHPUnit as well. This tool is great for unit testing PHP applications. Just for your information, PHPUnit 7 is out now. So you might want to check this article again with the latest version in mind.

    ReplyDelete