14

I have got a problem with mocha tests around global object I'm using with Node.js.

In index file, I set value to global variable

// index.js
global.enums = enumTemp

export default app

And then used it in another file

// other.js

status = global.enums.object.status

It's REST API and runs well if I made a request to a server. However, when I use a Mocha test, it seems to I cannot get the value for Node.js global variable. Any idea everyone?

4
  • 1
    Is there a reason why the variable has to be a global? Globals are ugly because they cause all kinds of headaches. You should think about putting the variable in its own module and require it where needed. Commented Jul 12, 2017 at 7:20
  • This variable I used to get data from database when I start up the server and then use the global variable in another file. Commented Jul 12, 2017 at 7:21
  • When do you set the variable as global? If there's a DB involved, it sounds like an async task to me. You should probably wait until the value if available before using it: to do this either you export a promise from the file that fetch the value or you get the value from where you need it. As a side note, I agree with @TobiKremer on global variables. Commented Jul 12, 2017 at 8:46
  • 1
    I already used Promise to make sure that had data from database on hands. The problem here is how to use the global variable with Mocha. I have found the solution works for me. Anyway, thank everyone for your concern. :) Commented Jul 12, 2017 at 8:54

3 Answers 3

22

I have found a solution that works for me by using Mocha hooks to set global variable just for testing:

// setup.test.js
import MyFunc from '../helpers/my-func'

before((done) => {
  MyFunc.then((variable) => {
    global.variable = variable
    done()
  })
})

We can use the global.variable in the test just like in the real code.

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

1 Comment

What exactly is in helpers/my-func.js? I can see that it loads some form of Promise, but I'm not sure why.
1

Just set a global variable using global object in node:

import {describe, test} from "mocha";

describe("suite", function () {
  test('test', function () {
    // given
    global.myVariable = myVariable;

    // when
    
  });
});

Having said that, you probably shouldn't use global variables since they implicitly couple parts of your design together.

Comments

0

You should get rid of the globals because they're ugly, which will probably solve your problem as well.

There's a somewhat little known fact about the way Node.js require() works: Modules are cached on the first require. This makes it possible to run costly calculations (or fetch something from the database) and have it cached on subsequent uses of the module.

Observe this example:

randomnumber.js

const calculateRandomNumber = limit => {
  console.log('calculateRandomNumber called');
  return parseInt(Math.random() * limit);
};

module.exports = calculateRandomNumber(1000);

other.js

module.exports = require('./randomnumber');

test.js

const randomnumber = require('./randomnumber');
const other = require('./other');
console.log(randomnumber);
console.log(other);

This will output the same random number twice and calculateRandomNumber is called only once, even though the randomnumber module has been required in different places.

6 Comments

Global variables are valuable in the right situation. 'You should get rid of them' is not constructive.
There might be cases where globals help (setting globals.Promise to a different Promise library comes to mind). But IMHO most of the time you can and should get rid of them because having state or action potentially far away from the code makes it harder to follow and reason about.
IDK if you solve the Toan Troan's problem but you surely solve mine. I didn't know and I don't know why I never thought about testing the times a module gets executed. Thank you mate.
If your code is sufficiently complex (or is likely to grow to be sufficiently complex) that you need to write tests, globals are probably hurting rather than helping you, and getting rid of them where possible is a good idea. However, it's not always possible, particularly if you've got a large legacy codebase. 'You should get rid of them' isn't constructive, not because they're valuable but because sometimes they're unavoidable.
No offense, but are we really discussing whether globals are considered bad practice? I already said that you should get rid of them if possible (like in the OP's example). I even gave an example when they might be useful, so you are just reiterating what I already said. State held in a global variable which is modified from all over your code makes it inherently harder to know what's going on compared to locally scoped variables rather than not. If you need shared state and you always reach for globals, you'll be having a hard time down the line.
|

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.