The design of the code which contains the main logic of the application that I’m currently working on looks a bit like the diagram on the right hand side:
We load a bunch of stuff from an Oracle database, construct some objects from the data and then invoke a sequence of methods on those objects in order to execute our domain logic.
Typically we might expect to see unit level test against all the classes described in this diagram but we’ve actually been trying out an approach where we don’t test the orchestration code directly but rather only test it via the resource which makes use of it.
We originally started off writing some tests around that code but they ended up being really similar to our database and resource tests.
Having them around also made it difficult to change the way the orchestration worked since we’d end up breaking most of the tests when we tried to change anything.
One disadvantage of not testing this code is that we end up using the debugger more when trying to work out why resource tests aren’t working since we now have more code being directly tested.
On the other hand we’ve been forced to drive logic into the domain objects as a result since we don’t have any other place to test that functionality from.
Testing directly against the domain objects is much easier since everything’s in memory and we can easily setup the data to be how we want it to be and inject it into the objects.
Another approach we could have taken would be to mock out the dependencies of the orchestration code but since this code is mostly coordinating other classes there are a lot of dependencies and the tests ended up being quite complicated and brittle.
Initially I was of the opinion that it wasn’t a good idea to not test the orchestration code but looking back a month later I think it’s working reasonably well and putting this constraint on ourselves has made the code easier to change while still being well tested.