首页 > 解决方案 > 在每个 Jest 测试中模拟不同的 TypeScript 常量

问题描述

我正在努力在每个测试的基础上用 Jest 模拟一个常量。我让它与下面的代码一起工作,但模拟是“静态的”——我不能为每个测试以不同的方式模拟它。

代码:

// allowList.ts
export const ALLOW_LIST = {
  '1234': true
};
// listUtil.ts
import { ALLOW_LIST } from './allowList.ts';

export const checkList = (id: string) => {
  if (ALLOW_LIST[id]) return true;
  return false;
};

测试(工作):

// listUtil.test.ts
import { checkList } from './listUtil';

jest.mock('./listUtil', () => {
  return {
    '5678': true
  };
});

test('in list', () => {
  expect(checkList('5678')).toBe(true);
});
test('not in list', () => {
  expect(checkList('1234')).toBe(false);
});

我想要的(不工作):

// listUtil.test.ts
import { checkList } from './listUtil';

test('in list', () => {
  jest.mock('./listUtil', () => {
    return {
      '5678': true
    };
  });
  expect(checkList('5678')).toBe(true);
});
test('not in list', () => {
  jest.mock('./listUtil', () => {
    return {
      '9123': true
    };
  });
  expect(checkList('1234')).toBe(false);
});

我正在尝试做的事情可能吗?这篇文章非常相似,并且在模拟函数时似乎可以工作,但我遇到了与接受答案的评论者相同的问题。我想我只是不明白 Jest 如何在幕后进行嘲笑。我相信工作版本可以工作,因为模拟被提升并且基本上覆盖了真实的实现,但我不确定我如何或是否可以在每次测试中实现这一点。

我认为一种选择是通过函数公开 ALLOW_LIST:

// allowList.ts
const ALLOW_LIST = {
  '1234': true
};
export const getAllowList = () => ALLOW_LIST;

并嘲笑它,但我想知道这是否有必要。

标签: typescriptunit-testingjestjsmockingts-jest

解决方案


您可以使用jest.doMock(moduleName, factory, options)为每个测试以不同方式模拟模块。

例如

allowList.ts

export const ALLOW_LIST = {
  '1234': true,
};

listUtil.ts

import { ALLOW_LIST } from './allowList';
console.log('ALLOW_LIST: ', ALLOW_LIST);

export const checkList = (id: string) => {
  if (ALLOW_LIST[id]) return true;
  return false;
};

listUtil.test.ts

describe('65712158', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('should in list', () => {
    jest.doMock('./allowList', () => ({ ALLOW_LIST: { 5678: true } }));
    const { checkList } = require('./listUtil');
    expect(checkList('5678')).toBeTruthy();
  });

  it('should not in list', () => {
    jest.doMock('./allowList', () => ({ ALLOW_LIST: { 9123: true } }));
    const { checkList } = require('./listUtil');
    expect(checkList('1234')).toBeFalsy();
  });
});

单元测试结果:

 PASS  examples/65712158/listUtil.test.ts
  65712158
    ✓ should in list (2517 ms)
    ✓ should not in list (2 ms)

  console.log
    ALLOW_LIST:  { '5678': true }

      at Object.<anonymous> (examples/65712158/listUtil.ts:2:9)

  console.log
    ALLOW_LIST:  { '9123': true }

      at Object.<anonymous> (examples/65712158/listUtil.ts:2:9)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |     100 |      100 |     100 |     100 |                   
 listUtil.ts |     100 |      100 |     100 |     100 |                   
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        5.03 s

推荐阅读