如何在开玩笑中嘲笑导出的const

2022-08-30 04:58:52

我有一个依赖于导出变量的文件。此变量设置为,但如果需要,可以手动设置为手动,以防止下游服务请求时的某些行为。consttruefalse

我不确定如何在Jest中模拟变量,以便我可以更改其值以测试和条件。consttruefalse

例:

//constants module
export const ENABLED = true;

//allowThrough module
import { ENABLED } from './constants';

export function allowThrough(data) {
  return (data && ENABLED === true)
}

// jest test
import { allowThrough } from './allowThrough';
import { ENABLED } from './constants';

describe('allowThrough', () => {
  test('success', () => {
    expect(ENABLED).toBE(true);
    expect(allowThrough({value: 1})).toBe(true);
  });

  test('fail, ENABLED === false', () => {
    //how do I override the value of ENABLED here?

    expect(ENABLED).toBe(false) // won't work because enabled is a const
    expect(allowThrough({value: 1})).toBe(true); //fails because ENABLED is still true
  });
});

答案 1

如果将 ES6 模块语法编译为 ES5,则此示例将起作用,因为最终,所有模块导出都属于同一个对象,可以对其进行修改。

import { allowThrough } from './allowThrough';
import { ENABLED } from './constants';
import * as constants from './constants';

describe('allowThrough', () => {
    test('success', () => {
        constants.ENABLED = true;

        expect(ENABLED).toBe(true);
        expect(allowThrough({ value: 1 })).toBe(true);
    });

    test('fail, ENABLED === false', () => {
        constants.ENABLED = false;

        expect(ENABLED).toBe(false);
        expect(allowThrough({ value: 1 })).toBe(false);
    });
});

或者,您可以切换到原始的commonjs函数,并在以下的帮助下这样做:requirejest.mock(...)

const mockTrue = { ENABLED: true };
const mockFalse = { ENABLED: false };

describe('allowThrough', () => {
    beforeEach(() => {
        jest.resetModules();
    });

    test('success', () => {
        jest.mock('./constants', () => mockTrue)
        const { ENABLED } = require('./constants');
        const { allowThrough } = require('./allowThrough');

        expect(ENABLED).toBe(true);
        expect(allowThrough({ value: 1 })).toBe(true);
    });

    test('fail, ENABLED === false', () => {
        jest.mock('./constants', () => mockFalse)
        const { ENABLED } = require('./constants');
        const { allowThrough } = require('./allowThrough');

        expect(ENABLED).toBe(false);
        expect(allowThrough({ value: 1 })).toBe(false);
    });
});

答案 2

在ES6 +中还有另一种方法可以做到这一点,并且由于getters和spyOn,可以玩笑22.1.0 +。

默认情况下,您无法监视基元类型,如布尔值或数字。但是,您可以将导入的文件替换为自己的模拟。getter方法仍然像原始成员一样工作,但允许我们监视它。在我们的目标成员上有间谍,你基本上可以随心所欲地使用它,就像模拟一样。jest.fn()

下面是一个例子

// foo.js
export const foo = true; // could be expression as well
// subject.js
import { foo } from './foo'

export default () => foo
// subject.spec.js
import subject from './subject'

jest.mock('./foo', () => ({
  get foo () {
    return true // set some default value
  }
}))

describe('subject', () => {
  const mySpy = jest.spyOn(subject.default, 'foo', 'get')

  it('foo returns true', () => {
    expect(subject.foo).toBe(true)
  })

  it('foo returns false', () => {
    mySpy.mockReturnValueOnce(false)
    expect(subject.foo).toBe(false)
  })
})

在文档中阅读更多内容。