An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

REST Adapter and Test Cases

September 1, 2006 · No Comments

Back in early July, I talked about unit testing for a REST adapter I was developing. In mid-August, I made the adapter available. In a comment on the original entry, Kurt Bonnet asks:
Sean, any chance you may release the unit tests for this? I'd love to see some "Real World" test cases for a component like this.
Yup! I've updated the ZIP file (12Kb) to include the cfcUnit test case and helper CFC.He continues:
Actually, I'd love to get your thoughts on how to design "Testable" software and how it relates to the whole Bean, DAO, Gateway, Service patterns. I'm battling between merging my Beans and DAOs to have a "Smart/Non-Anemic" model, and I'm also thinking about merging my Service and Gateway objects since services always seem to pass-through calls to my gateways. Obviously if I kept them all separate, I wouldn't have to worry about my persistence layer so much when testing, thus reducing the # of variables. However I'm in a mental battle over reducing "busy work" and maximizing cohesion, yet still keeping things maintainable. There's quite a battle going on :)
It's a very interesting question! I think there are a couple of separate concerns here tho'. First off, let's cover the "anaemic domain model" issue. This isn't just a matter of whether to have separate beans and DAOs etc. Your data tier should remain separate from your business tier but you'll get what looks like an anaemic domain model if your business tier contains only lightweight beans and "service" (or manager) objects. In other words, you have data containers (beans) and procedural objects (managers) instead of rich business objects that contain both data and the methods that operate on them. Similarly, the service / gateway comment Kurt makes is also related to this separation of business tier and data tier. Again, the real key here is the service / bean dichotomy. Merging beans and DAOs together, and services and gateways together, will not create a less anaemic domain model - instead it will simply make code harder to test. Which brings me to the second point. How do you write testable software? One key issue here is how you write a repeatable, isolated test case. Any code that modifies the database is harder to test than code that is independent of the "history" inherent in a database. Therefore, keeping your DAOs and gateways separate from your business objects will make it easier to test your business objects. In particular, you can create "mock" data tier objects as part of your test suite that provide canned data to your business objects so that you can guarantee the "data environment" for your business objects under test. How does my team do that at Adobe? We use ColdSpring for wiring together our applications and also for wiring together our test cases. In the test suite configuration, we load additional ColdSpring XML files that define any necessary "mock" versions of the data tier objects used in the tests. What else can you do to make software more testable? Make sure your business objects are cohesive (do a single, well-defined function) and loosely-coupled (both from each other and, more importantly, from their environment). Cohesive objects are easier to write test cases for because they are focused on a small, self-contained subset of the application functionality. Loosely-coupled objects are easier to write test cases for because they do not depend on other code or data. In particular, you don't want business objects that depend on shared scopes directly because your test case then has to manage that data as well as test the underlying business object. Write objects that return results that depend only on their arguments and a few, well-defined interfaces (such as a part of the data tier - that can be mocked up for testing purposes). Seriously consider test-driven development. In other words, write your test cases first for each method your business object will have. Obviously those tests will fail until you write the methods and have them return something. Then write just enough of the methods to get the tests to pass - have them return fixed result data at first, just to get the tests to pass. Then write more comprehensive tests (which will fail) and go back and start fleshing out your business methods. Rinse and repeat until you have a good, solid test suite and, almost coincidently, a good, solid business object! How much test code should you write? Take a look at the REST endpoint CFC and the test case code: the endpoint CFC (the "business" object) is about 15Kb and the test case code is about 28Kb.

Tags: coldfusion · tdd

0 responses so far ↓

  • There are no comments yet...Kick things off by filling out the form below.

Leave a Comment

Leave this field empty: