Lately I have been writing tests for a large JavaScript project. When testing helper functions, it occurred to me developers usually write the code for the perfect scenario without considering anything that could go wrong.
Let’s imagine we have a function to make a salad. This function expects an array of ingredients, put them together and return the result. In JavaScript, its simplest form would be:
Alright, we can now create a salad:
Very good. Now what happens if we call makeSalad(..)
without any ingredients? Or if we call makeSalad(..)
with something else than ingredients? Well let’s see.
Indeed. Because we did not pass ingredients
, its value is undefined
which does not have a join(..)
function. A simple fix would be to set a default value for ingredients
.
Now we can safely make our salad without passing any ingredients without risking a script crash. It will return an empty string. Given that the function usually returns a string, that seems like a valid way of handling this edge case.
Now what about the case where we pass something else than an array?
Again, ingredients
is an object and an object does not have a join(..)
function. To prevent this code from failing, we could add an extra check to our function to make sure that the given arguments is an array.
In this case, the script will still throw an error but the error will be very explicit, which is much better for catching and debugging.
Long story short: handle edge cases in your functions. Don’t assume anything, and provide meaningful fallbacks and errors.