Recently I had cause to develop a web service and so I wrote some tests to go along with it - or I was about to. When I looked at the asserts available in Zend_Test, they were all geared towards HTML/CSS output - but we can test just as effectively on another output.
Using Zend_Test, I set up the request object I wanted to send, and dispatched it. Then I retrieved the body and, since this service returns JSON, I json_decoded it. This gives me an object - and I can go ahead and use all the functionality of PHPUnit, with or without Zend_Test's additions, to test my service. Its perhaps easiest to show this in a few steps.
Setting up the request object
The idea here is that you set up any parameters you need to including the HTTP verb to use and cookies if needed, then despatch the request. Here's a few examples, first a simple GET method, with a cookie.
$request = $this->getRequest(); $request->setMethod('GET'); $request->setCookie('token','xxxx'); $this->dispatch('/user/24');
Including data with a POST request:
$request = $this->getRequest(); $request->setMethod('POST'); $request->setPost(array( 'name' => 'new user', 'organisation' => 49 )); $this->dispatch('/user');
This is a REST service, so I also tested PUT and DELETE methods. DELETE just needs the setMethod() call since it doesn't have any data with it, but PUT was a bit trickier - here's an example of what I used:
$request = $this->getRequest(); $request->setMethod('PUT'); $params = array('name' => 'Harry Potter'); $request->setRawBody(http_build_query($params)); $this->dispatch('/user/48');
Decoding the Response
This is the easy part, all I do is check the status code is what was expected, and then decode the response. My web service returns JSON so this part of each test looks something like:
$this->assertResponseCode('200'); $response = json_decode($this->getResponse()->getBody());
Testing the content of the response
Here we get into classic PHPUnit territory and simply use the assertTrue and assertEquals calls we'd use when testing anything else, an example is included for completeness:
$this->assertEquals($response->contentType, 'user'); $this->assertTrue(is_numeric($response->id)); $this->assertEquals($response->name, 'new user'); $this->assertEquals($response->organisation, 49);
By combining the request/response awareness of Zend_Test with standard PHPUnit testing strategies, its easy to test web services as well as web pages. I hope the examples are helpful - if they help you or if you have anything to add, then leave a comment!