0

So I'm working with an enterprise tool where we have javascript scripts embedded throughout. These scripts have access to certain built-in objects.

Unfortunately, the tool doesn't give any good way to unit test these scripts. So my thinking was to maintain the scripts in a repo, mock the built-in objects, and then set up unit tests that run on my system.

I'm pretty ignorant to how JavaScript works in terms of building, class loading, etc. but I've been just trying things and seeing what works. I started by trying out Mocha by making it a node project (even though it's just a directory full of scripts, not a real node project). The default test works, but when I try and test functions from my code, I get compiler errors.

Here's what a sample script from my project looks like. I'm hoping to test the functions, not the entire script:

var thing = builtInObject.foo();
doStuff(thing);
doMoreStuff(thing);

function doStuff(thing) {
    // Code
}

function doMoreStuff(thing) {
    // More Code
}

Here's what a test file looks like:

 var assert = require('assert');
 var sampleScript = require('../scripts/sampleScript.js');

 describe('SampleScript', function() {
    describe('#doStuff()', function() {
         it('should do stuff', function() {
              assert.equal(-1, sampleScript.doStuff("input"));
         });
     });
 });

Problem happens when I import ("require") the script. I get compilation errors, because it doesn't builtInObject. Is there any way I can "inject" those built in objects with mocks? So I define variables and functions that those objects contain, and the compiler knows what they are?

I'm open to alternative frameworks or ideas. Sorry for my ignorance, I'm not really a javascript guy. And I know this is a bit hacky, but it seems like the best option since I'm not getting out of the enterprise tool.

1 Answer 1

1

So if I get it right you want to do the unit tests for the frontened file in the Node.js environment.

There are some complications.

First, in terms of Node.js each file has it's own scope so the variables defined inside of the file won't be accessible even if you required the file. So you need to export the vars to use them.

module.exports.doStuff = doStuff; //in the end of sample script

Second, you you start using things like require/module.exports on the frontend they'll be undefined so you'll get an error.

The easiest way to run your code would be. Inside the sample script:

var isNode = typeof module !== 'undefined' && module.exports;
if (isNode) {
    //So we are exporting only when we are running in Node env.
    //After this doStuff and doMoreStuff will be avail. in the test
    module.exports.doStuff = doStuff;
    module.exports.doMoreStuff = doMoreStuff;
}

What for the builtInObject. The easies way to mock it would be inside the test before the require do the following:

global.builtInObject = {
    foo: function () { return 'thing'; }
};

The test just passed for me. See the sources.

Global variables are not good anyway. But in this case seems you cannot avoid using them.

Or you can avoid using Node.js by configuring something like Karma. It physically launches browser and runs the tests in it. :)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, your approach works for me for the most part! A couple follow up questions: 1. Can I predefine a class as well? There is code like "var builtInClass = new BuiltInClass();" as well. 2. Can I mock a function's return (like thenReturn() in java mockito)? When I'm testing doMoreStuff, I don't want doStuff to actually get called, but I may need the return value from that. @antonio-narkevich
I think I sort of figured out #2. Using sinon.stub I can mock the return of doStuff(). Problem is, the way my code is written right now, it needs the function mocked or it fails at require(). And mocking the function needs to happen after the require. I think I may be able to refactor my code to get around this. Edit: Yea I figured out a way. Sorry for turning this into my coding thought process blog.
Hey man. Regarding the #1. Probably you'll be able to do something like globa.BuiltInClass = function () {} and you'll be alright. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.