Today I found myself at a crossroads regarding testing. In my efforts to have pure unit tests, I had created tests with no assertions. Each test contained a mock object that verified multiple expectations, but no assertions. While each mock expectation could be thought of as an assertion, is it really a good idea to test the algorithm?
I say no.
The algorithm shouldn’t matter. The only thing that should matter is the input and output of each function.
Now I found my tests are much more stable and not nearly as much of a pain to write. I am setting up my expectations for input and output, but not regarding how to get there.
As you might expect though, the tests aren’t isolated to one class. They cross a few class boundaries, but not layer boundaries.
Have I traded one evil for another? I honestly don’t know, but I am going with my gut, and what makes sense. Having no assertions isn’t right in my opinion. What do you think?
You should have a line in your test that verifies your exceptions. If the exceptions have not been met then your test will fail. Furthermore, many mock object libraries support a strict behavior, where any unexpected call will fail the test.
You are not testing the algorithm. You are testing the way a dependency is consumed. This is an important distinction.
I am not advocating for not testing the methods outputs. But if data from a dependent object is used to generate output data, then using a mock becomes even more important because it helps you set up conditions that you might otherwise have difficulty. One example is testing how exceptions are handled.
I do think that you are on to something with the assertion-less test, though. I would agree that it is a smell that should be avoided. However, I am having trouble thinking of situations where mocks are the cause of such a smell.
It is important to unit test your classes in isolation, so that a bug in one class will not cause a failure in the test for a class that depends on it.
I think it comes down to state versus interaction testing:
http://codebetter.com/blogs/jeremy.miller/articles/129544.aspx
State-based tests will generally be easier to read and maintain, but there are situations where interaction tests make more sense. If you have a test that makes heavy use of strict mocks, it should probably raise a red flag and you may want to revisit your design, but it doesn’t necessarily mean you did something wrong.