3

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…

  1. Mock the model

    • mock Post.recent
    • make a request to /posts
    • assert that Post.recent was called
  2. 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?

1

1 Answer 1

1

Integration tests help test that the interactions between all your objects work correctly. And helps to outline the expected functionality of the entire system. These tests are the similar to the ones where you actually try the system out and make sure that it works. Or that QA would use to give the system a once over.

You are not concerned with any of the details in your controller and model with this test. All you want is that when you make a given request to the system, a given response is returned by the system. Having these tests would benefit you so that when you refactor your controller or model, you are able to verify that you have not broken any existing functionality. Changes to the models that are being used are transparent to these tests.

Why bother with mocking/stubbing? This is to verify that the individual components of your system work. For example, with your controller, you would want to inject mock models into it so that you can control what they return. This way you verify that an individual piece (the controller) works as intended.

By doing this, if there is a problem with your code (found either as a bug or failing integration test) you know that all your components are working correctly and only need to investigate the interactions between them.

When you are writing tests, you are not testing specific components per se. Rather you are testing that specific results will happen for given inputs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.