Suppose I'm building a JSON API and would like to include an endpoint that returns a list of recently created posts. Somewhere in my system is an existing Post model with the following test:
- create a few posts in the db (some new, some old)
- posts = Post.recent
- assert that posts only contains new posts
Now I want to test drive the JSON endpoint wrapping this functionality (the "controller"). The most obvious way to test this would be a full integration test like:
- create a few posts in the db (some new, some old)
- make a request to /posts
- assert that only the new posts were returned in the response
This seems to duplicate much of what is already being tested in the model and will start to slow down the test suite as more code paths need to be tested (i.e. auth, query string params, etc.). The alternatives…
Mock the model
- mock Post.recent
- make a request to /posts
- assert that Post.recent was called
Stub the model
- stub Post.recent
- make a request to /posts
- assert that the stubbed posts were return in the response
Either one of these options alone does not seem sufficient to fully test the controller but when combined seems fairly comprehensive. The piece that remains untested is the agreement between the model and controller about Post.recent. What if I decide to refactor my model and model tests and Post.recent no longer exists…my tests will still pass even though the production system will fail.
How does one address this? Are integration tests the only answer? If so, why bother stubbing and mocking at all?