【问题标题】:Jest - Mock a constant property from a module for a specific testJest - 为特定测试模拟模块中的常量属性
【发布时间】:2019-08-03 20:38:14
【问题描述】:

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

我在以下位置定义了一些常量: ` //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...
    })

`

I've tried this - 没有运气,它不会改变实际值

我已尝试将常量导出更改为导出对象(这不起作用)

我已经尝试为我的测试文件中的常量添加一个 jest.mock(..) 并在不需要模拟的测试中取消模拟。

我尝试在需要更改值的测试函数中添加 jest.doMock(...)。 (连同 jest.resetModules 和另一个要求)

我尝试在测试 beforeEach 中添加一个 jest.doMock(...)(以及 jest.resetModules 和另一个 require)

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

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

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

然后我在测试中添加了jest.mock("../constants);

然后我还在测试中添加了const funcImTesting = require("../../file").testFunction

常数保持不变,测试失败

【问题讨论】:

    标签: javascript unit-testing testing jestjs commonjs


    【解决方案1】:

    仅模拟一项测试:

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

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


    为每个测试提供一个模拟:

    1. 为您要模拟的模块创建一个__mocks__ 目录adiacent
    2. 提供实施
    3. 在您的测试中调用jest.mock('./moduleName')

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

    【讨论】:

    • 没错,我能做到。但是,由于有 2 个测试并且每个测试都测试不同的常量值......我无法看到模拟它进行 1 个单独的测试。所以它不是一个真正适用的解决方案
    • 我尝试将模拟模块添加到 a__mocks__ 目录,jest.mock 在测试中似乎什么都不做
    • 之后您可能需要依赖文件...或者请根据给定的场景更新您的问题。
    • 更新答案以反映当前情况
    【解决方案2】:

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

    // 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;
      });
    });
    

    【讨论】:

      【解决方案3】:

      遵循doc on 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');
        });
      });
      

      【讨论】:

        【解决方案4】:

        通过关注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, () => {
          constant.MY_CONSTANT = 'TEST'
          expect(constant.MY_CONSTANT).toBe('TEST')
        })
        
        it("Should do something else when MY_CONSTANT !== "TEST, () => {
          constant.MY_CONSTANT = 'NOT A TEST'
          expect(constant.MY_CONSTANT).toBe('NOT A TEST')
        })
        

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

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

        【讨论】:

          【解决方案5】:

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

          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
          });
          

          【讨论】:

            【解决方案6】:

            我通过在 reducer 中初始化 ContstantsFile.js 中的常量来解决这个问题。并将其放在 redux 商店中。由于 jest.mock 无法模拟 constantsFile.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 中模拟 store 并将值提供给我们想要的常量。

            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', () => { .....
            

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

            【讨论】:

              猜你喜欢
              • 2021-04-26
              • 1970-01-01
              • 2021-08-27
              • 2021-04-19
              • 1970-01-01
              • 1970-01-01
              • 2022-01-05
              • 1970-01-01
              • 2017-10-23
              相关资源
              最近更新 更多