0

I am new to unitTesting and using Mocha/Chai. I am trying to test if the function has a parameter and if it's a number.

// Main Function
function Sh(partnerUserId) {


  function validPartnerId(partnerUserId) {
    if (!partnerUserId);
    throw new Error("Missing partnerId");


    if (isNaN(partnerUserId));
    throw new Error("Not a number");

    return true;
  }
}



// Unit Test

var expect = chai.expect;

describe("Sh", function() {

    it('should check if the partnerId is provided', function(){
        ????
    });


    it('should check if the partnerId is a number', function(){
       ????
    });

});

I am open to suggestions if there is a better way to do it. I am trying to find how to capture the value of an argument and validate it in unit testing.

rex
  • 985
  • 5
  • 28
  • 48

2 Answers2

2

It is really not clear what you are going for with your Sohalo function. I've had to rewrite it to get a function that makes sense. At any rate, what you need to use to check whether the checks are happening is expect(fn).to.throw(...). The documentation for it is here. Note that when you want to check that a call with specific arguments throws an exception, the convenient way to do it is using bind. So something like:

expect(Sohalo.bind(undefined, 1)).to.not.throw(Error, "Not a number");

will test the call Sohalo(1). (The first argument to bind sets the value of this inside the function, and we don't need it here so I'm leaving it undefined).

So a file that would contain your function and test it could look something like this:

function Sohalo(partnerUserId) {
    if (typeof partnerUserId !== "number" || isNaN(partnerUserId))
        throw new Error("Not a number");
}

var chai = require("chai");
var expect = chai.expect;

describe("Sohalo", function() {
    it('should fail if partnerUserId is not given', function(){
        // This tests calling Sohalo with no arguments whatsoever.
        expect(Sohalo).to.throw(Error, "Not a number");
    });

    it('should fail if partnerUserId is not a number', function(){
        expect(Sohalo.bind(undefined, {})).to.throw(Error, "Not a number");
    });

    it('should fail if partnerUserId is NaN', function(){
        expect(Sohalo.bind(undefined, NaN)).to.throw(Error, "Not a number");
    });

    it('should not fail if the partnerUserId is a literal number', function(){
        expect(Sohalo.bind(undefined, 1)).to.not.throw(Error, "Not a number");
    });

    it('should not fail if the partnerUserId is a Number object', function(){
        expect(Sohalo.bind(undefined, Number(10))).to.not.throw(Error, "Not a number");
    });
});

In my test suites, I would typically perform tests with expect().to.throw but not with expect().to.not.throw. Instead of explicitly checking that the function does not throw, I'd just call it with good arguments and check that the results are correct. I'm using expect().to.not.throw here only for the sake of illustration.

Louis
  • 146,715
  • 28
  • 274
  • 320
0

Use something like this:

function isNumber(x) {
  return typeof x === 'number';
}

then, somewhere else you can use the isNumber function to determine if x is a number, and react accordingly:

function Sohalo (partnerUserId) {
  if (!isNumber(partnerUserId)) {
    // if it's not a number, throw exception
    throw new Error('partnerUserId needs to be a number!');
  }
  // ... do other stuff down here ...
}

Unit Test Suggestions:

Create an object like this:

var sohalo = (function () {
  var me = {},
      id;

  function isNumber(x) {
    return typeof x === 'number';
  }

  function isDefined(x) {
    return typeof value !== 'undefined';
  }

  me.validatePartnerId = function () {
    return isDefined(id) && isNumber(id);
  }

  me.setPartnerId = function (newId) {
    id = newId;
  };
  me.getPartnerId = function () {
    return id;
  };

  return me;
})();


describe('sohalo', function () {

  it('should check if the partner id is provided', function () {
    var id = sohalo.getPartnerId();
    id.should.equal(undefined);
  });

  it('should check if the partner id is a number', function () {
    sohalo.setPartnerId(5);
    sohalo.validatePartnerId().should.equal(true);
    sohalo.setPartnerId('5');
    sohalo.validatePartnerId().should.equal(false);    
  });
});

Here is a post I found that gives a little example: https://gist.github.com/michaelcox/3800736.

Hope this helps

pje
  • 2,458
  • 1
  • 25
  • 26
  • This will fail if the user passes in `NaN`. – Ruan Mendes Aug 25 '14 at 21:55
  • @JuanMendes Well, actually, despite the fact that NaN stands for 'Not-A-Number', it actually just means a value that cannot be specified within the limitation of the numeric type (for instance divide by 0). The actual `typeof NaN` returns 'number'. So, it is in fact of type `number`. More info here: http://stackoverflow.com/questions/2801601/why-does-typeof-nan-return-number. All this said, it depends on how you want things implemented. If you don't want `NaN` returning true for number type check, then add an extra check for this. – pje Aug 25 '14 at 22:10
  • Yes, since `typeof NaN` is `'number'`, the OP would want that to fail, which your code won't do.` It will also fail if you pass in `Number(5)` but it shouldn't? – Ruan Mendes Aug 25 '14 at 22:13
  • Hmm, well when I run it the way you described, it works: http://plnkr.co/edit/P21tSJ2QL3zEbzhA2G1P?p=preview. Also, not sure why you would ever need to wrap a primitive in its object type like that.. – pje Aug 25 '14 at 22:19
  • I meant `new Number(2)` http://plnkr.co/edit/ToLOQ05sR9kG690NAzqG?p=preview . There's no good reason to do it, but it's possible that some code may do it, so you should prevent against it, the OP is trying to be extra defensive – Ruan Mendes Aug 25 '14 at 22:48
  • Well, first of all, you should never use the `Number` constructor directly like that. But, if you did, things still work. The reason the `isNumber` function returns false for this is because calling `new Number(2)` is actually creating a Number `object` (of type `Object`), so `isNumber` is still returning the correct result. That is, detecting whether a variable `x` is `typeof` number. – pje Aug 26 '14 at 13:50
  • But a function that expects a number primitive should work if it gets a `Number` object, you should not throw an error just because someone boxed it – Ruan Mendes Aug 26 '14 at 14:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60026/discussion-between-pje-and-juan-mendes). – pje Aug 26 '14 at 16:38