How to sandbox Jest tests

Viewed 2938

According to Jest docs:

"Sandboxed test files and automatic global state resets for every test so no two tests conflict with each other."

However my tests conflict.

Code:

// Note: op is from object-path module for deep access by dot path
let config = { name: 'Bob' }

const getConfig = path => {
  return op.get(config, path) 
}

const setConfig = (path, value) => {
  return op.set(config, path, value)
}

Tests:

test('setConfig() updates a deep config value', () => {
  const { setConfig, getConfig } = require('services/config')

  setConfig('name', 'Woot')
  const res = getConfig('name')
  expect(res).toBe('Woot')
})

test('getConfig() updates a deep config value', () => {
  const { getConfig } = require('services/config')

  const res = getConfig('name')
  expect(res).toBe('Bob') // Actually Woot
})

The first test modifies the config file causing second test to fail.

From my experience things like process.env do not get sandboxed but this? What am I not understanding about "sandboxing"?

1 Answers

It seems like sandboxing in Jest only happens for files by default, and not for individual tests within the same file.

This is because Jest doesn't uncache the modules by default.

However it does provide a function, jest.resetModules that you to call before each test:

beforeEach(() => {
  jest.resetModules()
});

This will uncache your modules and enable sandboxing.
You can also configure Jest by setting resetModules in your package.json:

{
  "name": "my-project",
  "jest": {
    "resetModules": true
  }
}

To take advantage of these settings you need to require your modules in each test (which you are already doing). I'm just mentioning this because even if you called jest.resetModules, your tests would have failed if you had a single require at the top of the file.

Related