views:

137

answers:

5

Let's say I've got a method that takes some arguments and stores them as instance variables. If one of them is null, some code later on is going to crash. Would you modify the method to throw an exception if null arguments are provided and add unit tests to check that or not? If I do, it's slightly more complicated since javascript has many bad values (null, undefined, NaN, etc.) and since it has dynamic typing, I can't even check if the right kind of object was passed in.

+5  A: 

I think it really depends on what sort of API you're unit testing. If this is a component designed and built for internal use only, and you know usage will be under certain constraints, it can be overkill to unit test for bad parameters. On the other hand, if you're talking about something for distribution externally, or which is used in a wide variety of situations, some of which are hard to predict, yes, checking for bad parameters is appropriate. It all depends on usage.

McWafflestix
+6  A: 

I think you really have 2 different questions here.

The first is what is the best practice for parameter input validation and the second is should your unit test handle test for these situations.

I would recommend that you either throw an Argument Exception for the parameter that was not supplied correctly to your function or some other variable/message that informs the calling function/user of the situation. Normally, you do not want to throw exceptions and should try to prevent the functions from even being called when you know they will fail.

For your unit test, you should definitely include NULL value tests to make sure a graceful result occurs.

RSolberg
I agree with this. Parameter testing should be done in the functions/methods *themselves* wherever appropiate (i.e. almost all of the time).
Noldorin
A: 

JavaScript has instanceof and typeof that can help you check what kind of objects are being passed to your functions:

'undefined' == typeof noVariable; // true
var noVariable = null;
'undefined' == typeof noVariable; // false
typeof noVariable; // 'object'
noVariable === null; // true

var myArray = [];
typeof myArray; // 'object'
myArray instanceof Object; // true
myArray instanceof Array; // true

var myObject = {};
typeof myObject; // 'object'
myObject instanceof Object; // true
myObject instanceof Array; // false

You can use these to set some default "bad" values for your instance variables:

function myFunction(foo,bar) {
    var foo = foo instanceof Array||[]; // If 'foo' is not an array, make it an empty one
    var bar = bar instanceof Number||0;

    // This loop should always exit without error, although it may never do a single iteration
    for (var i=0; i<foo.length; i++) {
        console.log(foo[i]);
    }

    // Should never fail
    bar++;
}

The or operator is also very useful:

function myFunction(blat) {
    var blat = blat||null; // If 'blat' is 0, '', undefined, NaN, or null, force it to be null

    // You can be sure that 'blat' will be at least *some* kind of object inside this block
    if (null!==blat) {
    }
}
brownstone
A: 

Also, don't forget that with JavaScript you can pass in fewer than or more than the expected number of parameters. You can check that too, if you like.

Nosredna
A: 

For creating robust and secure code, checking the edge cases is definitely important task. Positive and negative testing is always good for the quality. The lack of negative tests might bite you in the long run.

So I'd say it is better play it safe - do both. It's a bit more work, but if you can afford the time, then it'll be worth it. Taking the developer hat off and putting on the cracker hat can be very interesting sometimes.

Bleadof