如何使用Jest模拟模块实例的方法?

时间:2018-01-11 19:05:57

标签: javascript typescript jestjs

Test-connection.ts文件是:

import { IEnvironmentMap, load } from 'dotenv-extended';
import { getTokensWithAuthCode, sdk } from '../src/connection-manager';

describe('Box API connection tests', () => {

    jest.useFakeTimers();
    let boxConfig: IEnvironmentMap;

    beforeAll(() => {
        boxConfig = load({
            errorOnMissing: true,
        });
    });

    describe('getTokensWithAuthCode function Tests', () => {

        it('should reject a promise if there is wrong auth code provided', async () => {
            jest.mock('box-node-sdk', () => ({
                 getTokensAuthorizationCodeGrant: jest.fn(),
            }));

            await getTokensWithAuthCode();
            expect(sdk.getTokensAuthorizationCodeGrant).toHaveBeenCalled();
       });
   });
});

这是我的主程序文件 Connection.ts

import * as BoxSDK from 'box-node-sdk';
import { IEnvironmentMap, load } from 'dotenv-extended';
import {ITokenInfo} from '../typings/box-node-sdk';

const boxConfig: IEnvironmentMap = load({
     errorOnMissing: true,
});

export const sdk: BoxSDK = new BoxSDK({
     clientID: boxConfig.BOX_CLIENT_ID,
     clientSecret: boxConfig.BOX_CLIENT_SECRET,
});

export async function getTokensWithAuthCode() {

    return await new Promise((resolve: (tokenInfo: ITokenInfo) => void, reject: (err: Error) => void) => {

        sdk.getTokensAuthorizationCodeGrant(boxConfig.BOX_AUTH_CODE, null, (err: Error, tokenInfo: ITokenInfo) => {
            if (err !== null) {
                reject(err);
            }

            resolve(tokenInfo);
       });
});
}

当以jest --coverage运行时,它会抛出错误。我怀疑这是由于错误的模拟。你能帮助用jest正确实现这个模块的模拟吗?

1 个答案:

答案 0 :(得分:3)

模拟本身是正确的,但顺序不正确。 import语句是静态的,仅在顶层提升 - 因此getTokensWithAuthCode首先导入原始box-node-sdk模块。然后,由于加载的模块没有刷新内部加载的依赖项,因此模拟不会起作用。

解决这个问题的方法很多。

  1. 使用babel-jest,提升模拟到顶级。然后即使使用import语句,您的模拟将在导入之前被提升。例如

    import {getTokensWithAuthCode} ...
    jest.mock('box-node-sdk' ...);
    

    将正确订购

    jest.mock('box-node-sdk' ...);
    const {getTokensWithAuthCode} = require(...) //transpiled
    
    如果你正在使用TypeScript,

    ts-jest会为你做这件事。

  2. 在模拟您的依赖项后,在每个测试夹具中动态需要getTokensWithAuthCode

  3. 这两个都是关于订购模拟和真正的导入 - 这里的关键是你应该先使用工具或手动模拟。