How can I unit test failure cases?
- Magnus Therning
When writing unit tests, especially when using mock objects, there’s always a risk of falling into the trap of writing tests for the implementation rather than for the API. In my experience the most obvious indication of that is that any refactoring of the code requires major rework of the tests.
Right now I’m sitting with the task of writing tests for a function that promises to return NULL
on failure. The function in question allocates memory up to three times, opens two message queues, sends a message on one and expects a reponse on the other. If all goes well it returns the pointer to one of the memory areas allocated. And if it fails, for whatever reason, it returns NULL
.
Is it even possible to write a set of tests for it without testing the specific implementation?
I know some of the calls can be re-arranged, e.g. moving all memory allocation to the start of the function, without affecting the caller of the function. However, if I use mock objects to simulate failure in the external libraries and system calls I’d be forced to modify the tests on each such re-arranging of calls. In other words I’m testing the implementation!
Should I think differently about testing failure cases?
Should the API be changed in some way to make unit tests a better fit for testing failures?