Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asserting throws in tape - node

So I am trying to test out a function, it is a client-side function(un-finish) which is why it is embedded in the test itself(until I can figure out a better solution).

The problem I am having is when I test to see if the function is throwing a TypeError.

I understand the problem is because it is testing the return value and not the function itself, I am unsure how to work around this.

Any and All help is appreciated!

Tape


test.js

var test  = require('tape');


test('GenerateRandomNumber Tests', function(assert){  

  /**
   * Generates a random number between the min/max
   * @param {int} the min value 
   * @param {int} the max value 
   * @param {array} list of values already stored
   * @return {mixed} int if success, false if exception thrown
  **/
  var GenerateRandomNumber = function( min, max, tickets ){
        
    try{
      
      if(!tickets instanceof Array){
        throw new TypeError();
      }
      
      min = (min) || 0;
      max = (max) || 200;
      
      var n = 0;

      n = ~~(Math.random() * (max - min) + min); 
      
      if(tickets.indexOf(n) === 1){
        GenerateRandomNumber(min, max);
      }
      
      return n;
      
    }catch(e){ return false; } 
    
  };
  
  assert.plan(4);
  
  
  var t1 = GenerateRandomNumber(0, 300, null);
  assert.equal(typeof t1, "boolean", "Should return a boolean - false");
  
  var t2 = GenerateRandomNumber(0, 300, [0,1,2,3,4]);
  assert.equal(typeof t2, "number", "Should return a typeof number");
  
  // HELP
  assert.throws(GenerateRandomNumber(0, 300, null), TypeError, "Should throw typeError");
  
  var t4 = GenerateRandomNumber(null, null, [0,1,2,3,4]);
  assert.equal(typeof t4, "number", "Should return a typeof number");
  
  
});
like image 431
Philip Avatar asked Dec 07 '15 19:12

Philip


1 Answers

Well you're first problem is that !tickets instanceof Array is not the logic you want. What that does is first executes the not operation on tickets and then tests if that is an instanceof Array. So what you actually want is:

if(!(tickets instanceof Array)){
   throw new TypeError();
}

The next issue is that, like you said, you are getting the return value of GenerateRandomNumber, which if an error is thrown, is false not a TypeError. If you want to keep your try/catch and return false in GenerateRandomNumber then you don't need the throws test but rather something like:

assert.equal(GenerateRandomNumber(0, 300, null), false, "Should catch the TypeError and return false)

If you want to use assert.throws then you need to remove the try/catch from GenerateRandomNumber and instead do something like this:

var test  = require('tape');


test('GenerateRandomNumber Tests', function(assert){  

  /**
   * Generates a random number between the min/max
   * @param {int} the min value 
   * @param {int} the max value 
   * @param {array} list of values already stored
   * @return {mixed} int if success, false if exception thrown
  **/
  var GenerateRandomNumber = function( min, max, tickets ){
      if(!(tickets instanceof Array)){
        throw new TypeError('error');
      }

      min = (min) || 0;
      max = (max) || 200;

      var n = 0;

      n = ~~(Math.random() * (max - min) + min); 

      if(tickets.indexOf(n) === 1){
        GenerateRandomNumber(min, max);
      }

      return n;
  };

  assert.plan(3);

  var t2 = GenerateRandomNumber(0, 300, [0,1,2,3,4]);
  assert.equal(typeof t2, "number", "Should return a typeof number");

  // You must wrap GenerateRandomNumber from within another function 
  //so that the error being thrown doesn't cause the program to exit
  assert.throws(() => GenerateRandomNumber(0, 300, null), /error/, "Should throw typeError");

  var t4 = GenerateRandomNumber(null, null, [0,1,2,3,4]);
  assert.equal(typeof t4, "number", "Should return a typeof number");


});

I used the option to pass a RegExp because tape's matching of errors when passing a function as expected is quite strange (see this issue). Im looking into an option for doing it this way still, but hopefully this helps you for now.

like image 73
cbalos Avatar answered Oct 22 '22 00:10

cbalos