简体   繁体   中英

How to test a function in var in javascript

Given a piece of code like below, which is adopted from reinforcejs

var RL = {};
(function(global) {
    var sampleWeighted = function(p) {
        var r = Math.random();
        var c = 0.0;            // cumulative prob
        for(var i=0, n=p.length; i<n; i++) {
            c += p[i];
            if (c >= r) { return i; }
        }
        // assert(false) may happen if sum(p) < 1;
        assert(false, 'wtf');
    };

// many content omitted
...
})(RL);

export default RL;

How can I access sampleWeighted and test it, please? I have tried below

import RL from './rl.js';

it('sampleWeighted', () => {
    expect(RL.sampleWeighted([0.5, 0.5])).toEqual(1);
});

But it complains with error

 FAIL  src/lib/rl.test.js
  ✕ sampleWeighted (1ms)

  ● sampleWeighted

    TypeError: _rl.RL.sampleWeighted is not a function

      at Object.<anonymous> (src/lib/rl.test.js:7:46)
      at process._tickCallback (internal/process/next_tick.js:103:7)

I am new to javascript testing. Currently, I am using create-react-app to setup the testing framework. So what's the proper way to test the above function, please? If you happened to understand what sampleWeighted does, please feel free to comment on it, too.

sampleWeighted is in the closure of your IIFE (Immediate function invocation syntax)

this way you could keep your method private like private public in Java, notice you have pass the global which is RL, you can treat that as your namespace, and if you want to call sampleWeighted, you need to attach sampleWeighted to RL ,

...
RL.sampleWeighted = function() {}
...

Write code inside a closure that gives our test code access to the private functions we care about, but then remove that code when we deploy to production. here you can write your code exactly how you'd like it to appear when released, then add on whatever bridge code you need to expose the parts you want to test.

If you're using a build system, you can do exactly that.

var RL = {};
(function(global) {
    var sampleWeighted = function(p) {
        var r = Math.random();
        var c = 0.0;            // cumulative prob
        for(var i=0, n=p.length; i<n; i++) {
            c += p[i];
            if (c >= r) { return i; }
        }
        // assert(false) may happen if sum(p) < 1;
        assert(false, 'wtf');
    };

    var api = {
        bar: function() {
            // public function `bar` returned from closure
            return "bar"
        }
    };

    /* test-code */
        api._foo = foo
    /* end-test-code */

    return api    

})(RL);

export default RL;

and then you can use "grunt-strip-code"

npm install grunt-strip-code --save-dev

Then enable it inside your Gruntfile:

grunt.loadNpmTasks('grunt-strip-code');


grunt.initConfig({
  strip_code: {
    options: {
      start_comment: "test-code",
      end_comment: "end-test-code",
    },
    your_target: {
      // a list of files you want to strip code from
      src: "dist/*.js"
    }
  }
})


grunt.registerTask("test", [
  "concat",
  "jshint",
  "jasmine"
])
grunt.registerTask("deploy", [
  "concat",
  "strip-code",
  "jshint",
  "uglify"
])

Rerefence - https://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/

In your IIFE you have not attached sampleWeighted to the passed in object (global). So make sure you do something like below inside of your IIFE:

global.sampleWeighted = sampleWeighted;

Also, in your test file, you need to access that function using:

RL.sampleWeighted

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM