Megan
Megan

Reputation: 247

How to access global constant in unit tests with Jest?

I want to mock a global variable and test if it has been called in my function. In my file, I define a global variable "remote" which instanciates a Subject (RxJS library). I just want to test if the next function of Subject has been called with the right parameter "name". However, I can't access the global variable remote in my test file. I tried to mock it in my setup file, but doesn't work.

How can I do that ?

const remote = new Subject();
const analytics = {
  click: (name) => {
    if (name) {
      remote.next(name);
    }
  }
}
module.exports = analytics;

Thanks !

Upvotes: 1

Views: 2607

Answers (1)

Zen
Zen

Reputation: 5530

This is a good question. When you use webpack, your individual file is wrapped into different function call. Check out this doc.
The best part of this question is that it shows the necessity of IOC/DI if you want your code to be testable. Instead of defining remote in your local module, you can export an Analytics class and then inject remote to its constructor.

// Analytics.js
export default class Analytics{
  constructor(remote) {
    this.remote = remote
  }

  click(name) {
    if (name) {
      this.remote.next(name)
    }
  }
}

main.js
import Analytics from './Analytics'

const remote = new Subject()
const analytics = new Analytics(remote)
analysis.click('foo')

It would be tedious to inject dependencies to all components/services. Angular has an decent doc on why/how to simplify it. Hope this is helpful!

// Update
You can use window to define global constant and access it in tests by using window.remote

const remote = new Subject()
window.remote = remote

When you want to mock remote, remember to modify its properties rather than the reference to it.

// test.js
beforeEach(() => {
    // wrong !!!
    window.remote = {
        next(name) { assert(name) }
    }

    // right
    window.remote.next = name => assert(name)
})

Upvotes: 1

Related Questions