Helper functions, boilerplate tests and REST APIs

63 views
Skip to first unread message

Brian G

unread,
Apr 16, 2015, 8:40:28 AM4/16/15
to mxu...@googlegroups.com

Hi group, looking for direction from the masters.  I know MxUnit isn't under development but hopefully there are still a few brain cells circulating on the list. :)

1. How do you mock/set initial state when testing your own REST API?

We have a REST API (via PowerNap, but could be anything really) and we test it with CFHTTP.  When I test third party APIs, I generally capture the FileContent and turn them into mocks to let me run them offline for speed and refactoring of my local consumer code (I wrote about that at http://www.ghidinelli.com/2012/08/25/unit-testing-trick-developing-against-apis).  For testing my own API though, I had been using a procedural CFM file that performed the CRUD operations in order.  We're working to move this into a proper unit test so we can run it as part of our suite.  I'm not testing consuming code here, I'm really testing the server generation code as more of an integration test.

Here, I can't really use mocks or querysim or anything else because the data is coming from the API and that's precisely what I want to test.  Any suggestions on how I can get my data into a known state while also keeping it testable?  E.g., if my create() operation fails for network, code or any other reason, none of my tests will run but I also can't debug inside of beforeTests().  Not sure where the right place is to put a create() and a delete() call to keep the database in a known good, or at least testable, state.


2. Are boilerplate/helper functions in a test "bad"?

Say I'm testing the REST API and I get back a CFHTTP response - for every single expected success, I'm going to do a few common things which are a combination of guards and top-level assertions:

check the fileContent is JSON
deserialize the JSON
check if there is an "error" key in the struct
verify the http status code was 2XX

Likewise, for every error I'll have some equivalent set of checks.  What is the best practice on whether or not I should abstract those checks into a private method in my test CFC and call it?  Or should I duplicate those checks in each test?  Or should I only check them in one test because even if other tests depend on it, it's unnecessary to check them each time?

I will pay for answers in the form of beer at dev.Objective()! :)


Brian


Sean Coyne

unread,
Apr 16, 2015, 9:21:39 AM4/16/15
to mxu...@googlegroups.com
I would think that your API would be mostly sending input to your service layer, no?  The API itself shouldn't be doing the heavy lifting, so put your business logic in the services and unit test those.  Then you can mock the services to test your API layer.

Brian G

unread,
Apr 17, 2015, 3:09:31 PM4/17/15
to mxu...@googlegroups.com

Thanks Sean, it's actually the opposite problem.  The API calls our service layer and generates a developer-friendly interface by renaming certain attributes or flattening a 1-many relationship into a single REST call.  I need to test that valid HTTP requests to our API, such as a third party would make, return the correct results.  We have separate unit tests for the service layer to verify that it behaves properly.

Sean Coyne

unread,
Apr 20, 2015, 9:37:04 AM4/20/15
to mxu...@googlegroups.com
I guess I'm not following then.  I'm not sure why you can't mock your entire service layer then.  If you mock the service layer then hit your API in your unit tests using cfhttp, for example, would you not be testing only the API layer?  The service layer mocks would return known results, so you would be testing that your API takes the input, passes to the service layer (you can test that the mocked objects were called and that the arguments were what you expect), then you'd verify that you got JSON, no error key, correct status code, etc.
Reply all
Reply to author
Forward
0 new messages