DEV Community

Discussion on: How I learned to love unit testing

ravernkoh profile image
Ravern Koh

When building smaller APIs, I sometimes find that my end-to-end tests and unit tests for my controllers tend to overlap a lot. Since I usually don't have many middlewares, or the middlewares are out-of-the-box from libraries which are already well-tested, the two different kinds of tests usually end up doing the same thing which is a lot of duplication and mocking of services.

Am I assuming something wrong here or is the duplication really good/necessary?

quii profile image
Chris James • Edited on

It's quite likely your controllers are doing too much stuff.

Your controllers really only aught to be

  1. Parse & validate request
  2. Call some kind of service to do something useful
  3. Return a HTTP response according to 2.

If they do more, you probably should be refactoring logic out of your controller. Note how if you have a broad "service" later injected into your controller, you only need to mock the one thing

Another possibility is your end to end tests are too exhaustive. Google for Martin Fowler's test pyramid, the number of e2es should be small. Test the key business cases and then unit test everything else. This should give you enough confidence your system works and keeps your test suite from taking a long time to execute.

stegriff profile image
Stephen Griffiths Author

That's a great point Ravern, and I feel you - I've had the same thing. I think that you don't need to unit test things that are:

  • Features of an underlying dependency
  • Basic CRUD pipelines which don't alter or transform the data

But anything in your solution which is unique or original could be unit tested. For example:

  • Do you have data transfer objects which construct on top of data from another source? Test that they instantiate with the expected values
  • Do you parse/process/transform API data? Unit test your assumptions about that

Straightforward API projects often do some of the above.

That said, unit testing is a helper, not a law! Test what it's helpful to test. Your end-to-end testing sounds like it provides a lot of value, and perhaps in many cases that's all you need!

r0bnet profile image

Another thing to mention here: if something goes wrong in your application which (obviously) wasn't covered by any test then try to add a unit test for this particular case. If that isn't an option then you may write an integration test. If that isn't viable either than you are allowed to write and e2e test.

Why? Because unit tests are the cheapest tests you can run. Everything else is exepnsive in various ways.

You should keep in mind that if writing a unit test seems to be really hard your code may need some refactoring. This of course always sounds trivial but it's sometimes a hard thing to grasp at first. But it will pay off because you'll learn a lot. Just try!