Jest - 为特定测试模拟模块中的常量属性

问题描述 投票:0回答:7

所以,我正在尝试做一些表面上应该很简单的事情......

我定义了一些常量:

//constants.js

module.exports = {
 MY_CONSTANT: "TEST"
}

我有一个我正在尝试测试的文件,它有一个像这样的分支语句:

//file to test
//...
    
if(CONSTANTS.MY_CONSTANT === "TEST")
{...}
...

我有这样的测试:

//test
it("Should do something when MY_CONSTANT === "TEST, () => {
  //This is fine as it is exported as TEST
})
   
it("Should do something else when MY_CONSTANT !== "TEST, () => {
  //This seems annoyingly difficult to get working...
})

我试过这个 - 运气不好,它不会改变实际值

我试过更改常量导出以导出一个对象(那没有用)

我已经尝试为我的测试文件中的常量添加一个

jest.mock(...)
并在测试中进行取消模拟我不需要它们被模拟。

我试过在我需要更改值的测试函数中添加一个

jest.doMock(...)
。 (连同
jest.resetModules
和另一个要求)

我已经尝试在每个测试之前添加一个

jest.doMock(...)
(连同
jest.resetModules
和另一个要求)

我真的很茫然......实际上我想做的就是在测试运行之前更改属性值😂

更新
所以我做了一些提出的建议:

我现在在 constant 文件夹旁边有一个 mocks 文件夹 它包含一个与实际常量文件同名的文件和一个自定义导出

然后我在测试中添加了

jest.mock("../constants);

然后我还在测试中添加了一个

const funcImTesting = require("../../file").testFunction

仍然常数保持不变,测试失败。

javascript testing jestjs commonjs
7个回答
14
投票

导出我想要模拟的常量值的文件:

// utils/deviceTypeUtils file
import DeviceInfo from 'react-native-device-info';

export const isTablet = DeviceInfo.isTablet();

在我的测试文件中,我使用这段代码来模拟常量

isTablet

// file: deviceTypeUtils.spec
const DeviceTypeUtilsMock = jest.requireMock('../utils/deviceTypeUtils');
jest.mock('../utils/deviceTypeUtils', () => ({
  isTablet: false,
}));

describe('mock const example', () => {
  it('mock const `isTablet` to the value `true`', () => {
    DeviceTypeUtilsMock.isTablet = true;
  });

  it('mock const `isTablet` to the value `false`', () => {
    DeviceTypeUtilsMock.isTablet = false;
  });
});

8
投票

仅模拟一次测试:

jest.mock('./constants.js', () => ({
  MY_CONSTANT: 'something fake'
}));

https://jestjs.io/docs/en/manual-mocks


为每个测试提供模拟:

  1. create a
    __mocks__
    directory adiacent to the module you desire to mock
  2. 提供实施
  3. 在你的测试中调用
    jest.mock('./moduleName')

https://jestjs.io/docs/en/manual-mocks#mocking-user-modules


6
投票

我已经能够按照 https://mikeborozdin.com/post/changing-jest-mocks-between-tests/

上的帖子做类似的事情

这创建了一个模拟,然后为每个测试更改它。

import * as constants from './constants'

jest.mock('./constants', () => ({
  __esModule: true,
  MY_CONSTANT: 'SOME OTHER DEFAULT',
}))

it("Should do something when MY_CONSTANT === "TEST, () => {
  constants.MY_CONSTANT = 'TEST'
  expect(constants.MY_CONSTANT).toBe('TEST')
})

it("Should do something else when MY_CONSTANT !== "TEST, () => {
  constants.MY_CONSTANT = 'NOT A TEST'
  expect(constants.MY_CONSTANT).toBe('NOT A TEST')
})

如果您使用的是打字稿,则需要转换模拟以修改模拟值:

const mockConstants = constants as { MY_CONSTANT: string }
mockConstants.MY_CONSTANT = 'TEST'

5
投票

按照doc的指导

jest.doMock()

config.js
文件:

export const env = 'test';

myComponent.js
文件:

import {env} from './config.js';

export const MyComponent = () => {
  if (env === 'prod') {
    return (<Text>Prod Env</Text>);
  } else if (env === 'test'){
    return (<Text>Test Env</Text>);
  } else {
    return (<Text>Dev Env</Text>);
  }
};

myComponent.test.js
文件:

describe('Test MyComponent', () => {
  test('Test in prod env', () => {
    jest.doMock('./config', () => ({env: 'prod'}));
    const {MyComponent} = require('./myComponent.js');
    const myComp = mount(<MyComponent />);
    expect(myComp.find('Text')).toHaveText('Prod Env');
  });

  test('Test in test env', () => {
    jest.doMock('./config', () => ({env: 'test'}));
    const {MyComponent} = require('./myComponent.js');
    const myComp = mount(<MyComponent />);
    expect(myComp.find('Text')).toHaveText('Test Env');
  });

  test('Test in dev env', () => {
    jest.doMock('./config', () => ({env: 'dev'}));
    const {MyComponent} = require('./myComponent.js');
    const myComp = mount(<MyComponent />);
    expect(myComp.find('Text')).toHaveText('Dev Env');
  });
});

0
投票

我只是复制常量并在每个测试用例之后分配它们。

const constants = require('./constants');
const original = {...constants};
afterEach(() => {
    Object.assign(constants, original);
});
test('test1', () => {
    constants.ABC = 'whatever';
});
test('test2', () => {
    // constants.ABC is set back to original
});

0
投票

我通过在 reducer 中从 ContstantsFile.js 初始化常量来解决这个问题。并将其放在 redux 商店中。由于 jest.mock 无法模拟 contstantsFile.js

constantsFile.js
-----------------
const MY_CONSTANTS = {
MY_CONSTANT1: "TEST",
MY_CONSTANT2: "BEST",
};
export defualt MY_CONSTANTS;

reducers/index.js
-----------------
import MY_CONST from "./constantsFile";

const initialState = {
...MY_CONST
}
export const AbcReducer = (state = initialState, action) => {.....}

ABC.jsx
------------
import { useSelector } from 'react-redux';
const ABC = () => {
const const1 = useSelector(state) => state. AbcReducer. MY_CONSTANT1:
const const2 = useSelector(state) => state. AbcReducer. MY_CONSTANT2:
.......

现在我们可以轻松地在 test.jsx 中模拟商店并提供我们想要的常量值。

Abc.text.jsx
-------------
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';

describe('Abc mock constants in jest', () => {
const mockStore = configureMockStore([thunk]);
let store = mockStore({
   AbcReducer: {
      MY_CONSTANT1 ="MOCKTEST",
      MY_CONSTANT2 = "MOCKBEST",
   }
});

test('your test here', () => { .....

现在当测试运行时,它总是会从模拟商店中选择常量值。


0
投票

如果您想模拟模块中的特定常量并保留其他导出的值,您可以使用 jest 提供的 requireActual 方法并像这样覆盖特定值

jest.mock('./constants', () => ({
  ...jest.requireActual('./constants'),
  CONSTANT_TO_OVERRIDE: 3
}));

如果您的代码从一个模块导入多个值,而您只是想覆盖其中一个值,这将很有用。使用这种方法,您不必重新定义测试所消耗的所有值即可正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.