views:

479

answers:

2

I'm at the point where I need to write unit tests for a REST API written using CakePHP 1.3. The API supports GET, POST and PUT requests for querying and manipulating data.

Is there any established way to test the correct input/output of an API simulating an HTTP request, using fixtures? I do not want to run actual POST/PUT requests against the live (dev) database. How can I best mock out the system to use temporary models, yet test the rest of the stack as-is?


Testing GET requests is easy enough with controller tests. However, for data manipulation the API uses HTTP headers quite extensively and also parses raw XML and JSON POST/PUT data. The controller unit test methods only mock POST data by setting $this->data in the controller, which does not allow me to properly test the API.

+2  A: 

I'd recommend starting with a little research. These articles should help:

Craig Trader
+1  A: 

Looks like you might be able to test the raw XML PUT and POST data without too much trouble. The CakePHP REST documentation says this:

If a POST or PUT request has an XML content-type, then the input is taken and passed to an instance of Cake's Xml object, which is assigned to the $data property of the controller. Because of this feature, handling XML and POST data in parallel is seamless: no changes are required to the controller or model code. Everything you need should end up in $this->data.

Try stepping through your controller code in debug mode to see what actually comes in through $this->data during an XML request.

As for avoiding the live database, would a SQLite in-memory database be any easier?

Don Kirkby
I don't really care about what type of database I'm using, I want to use fixtures in test tables. These are only available through partly mocked objects, which requires me to skip some low level parts in the API. To test the complete API as a client would see it, I need access to raw POST/PUT data, because I'm a) doing a signature check on the posted data and b) also need to test posted JSON data. Faking the process with mock objects and setting `$this->data` directly works to some extend, but it doesn't allow me to test the whole API request/response cycle as one single unit.
deceze
I used test fixtures in some tests, @deceze, and I don't remember having to mock anything. The mocking was necessary to test the controller methods, I think. It's been a few months, so I may have forgotten some detail. I followed the directions here: http://book.cakephp.org/view/363/Testing-models
Don Kirkby
If you're trying to test the part of the cycle between http request and controller method, @deceze, then I would tackle that separately as an integration test. Just test it once because it's all handled by the CakePHP routing code. Then for each of your controller methods, you can write a simpler unit test without worrying about the routing.
Don Kirkby
That's apparently what I'll have to do, which is really unfortunate. Because it means I'll have to mock the hell out of some parts of the system that usually depend on actual requests. Also because it means I can't really write request/response tests to make sure the API works as expected from the POV of a client.
deceze