繁体   English   中英

在 Jest 中,如何仅在特定测试中模拟外部模块?

[英]In Jest, how do I mock an external module ONLY in a specific test?

我正在将 Jest 与 TypeScript 一起使用(使用ts-jest )。 这是我使用dotenv库的测试主题:

import * as dotenv from 'dotenv';

export class TestSubject {
  public function test() {
    console.log(dotenv); // Here I debug if I'm using a mock or not
  }
}

我只想为特定测试模拟dotenv库,但我被卡住了。

这是我的测试套件:

import { TestSubject } from './test-subject';
import * as dotenv from 'dotenv';

jest.mock('dotenv'); // place it here, otherwise it doesn't work

describe('Suite 1', () => {
  it('test 1', () => {
    // I want to use the mock here... and it works
    const subject = new TestSubject();
    subject.test(); // shows that I'm using the mock
  });

  it('test 2', () => {
    // I don't want the mock here
    jest.dontMock('dotenv'); // doesn't work
    jest.unmock('dotenv');   // doesn't work

    const subject = new TestSubject();
    subject.test(); // shows that I'm still using the mock!!!
  });
});

如您所见,调用jest.mock('dotenv')应该放在 describe 之外,否则,它不起作用。

我试图在test 2 中不使用模拟,但它不起作用: console.log显示我正在使用模拟。

这是解决方案:

index.ts ,文件将被测试:

import * as dotenv from 'dotenv';

export class TestSubject {
  public test() {
    console.log(dotenv);
  }
}

单元测试:

describe('TestSubject', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('should mock dotenv', () => {
    jest.doMock('dotenv');
    const dotenv = require('dotenv');
    const { TestSubject } = require('./');
    const subject = new TestSubject();
    subject.test();
    expect(jest.isMockFunction(dotenv.config)).toBeTruthy();
  });

  it('should not mock dotenv', () => {
    jest.unmock('dotenv');
    const dotenv = require('dotenv');
    const { TestSubject } = require('./');
    const subject = new TestSubject();
    subject.test();
    expect(jest.isMockFunction(dotenv.config)).toBeFalsy();
  });
});

单元测试结果:

 PASS  src/stackoverflow/56446543/index.spec.ts
  TestSubject
    ✓ should mock dotenv (2111ms)
    ✓ should not mock dotenv (2ms)

  console.log src/stackoverflow/56446543/index.ts:5
    { config: 
       { [Function: config]
         _isMockFunction: true,
         getMockImplementation: [Function],
         mock: [Getter/Setter],
         mockClear: [Function],
         mockReset: [Function],
         mockRestore: [Function],
         mockReturnValueOnce: [Function],
         mockResolvedValueOnce: [Function],
         mockRejectedValueOnce: [Function],
         mockReturnValue: [Function],
         mockResolvedValue: [Function],
         mockRejectedValue: [Function],
         mockImplementationOnce: [Function],
         mockImplementation: [Function],
         mockReturnThis: [Function],
         mockName: [Function],
         getMockName: [Function] },
      parse: 
       { [Function: parse]
         _isMockFunction: true,
         getMockImplementation: [Function],
         mock: [Getter/Setter],
         mockClear: [Function],
         mockReset: [Function],
         mockRestore: [Function],
         mockReturnValueOnce: [Function],
         mockResolvedValueOnce: [Function],
         mockRejectedValueOnce: [Function],
         mockReturnValue: [Function],
         mockResolvedValue: [Function],
         mockRejectedValue: [Function],
         mockImplementationOnce: [Function],
         mockImplementation: [Function],
         mockReturnThis: [Function],
         mockName: [Function],
         getMockName: [Function] },
      default: 
       { config: 
          { [Function: config]
            _isMockFunction: true,
            getMockImplementation: [Function],
            mock: [Getter/Setter],
            mockClear: [Function],
            mockReset: [Function],
            mockRestore: [Function],
            mockReturnValueOnce: [Function],
            mockResolvedValueOnce: [Function],
            mockRejectedValueOnce: [Function],
            mockReturnValue: [Function],
            mockResolvedValue: [Function],
            mockRejectedValue: [Function],
            mockImplementationOnce: [Function],
            mockImplementation: [Function],
            mockReturnThis: [Function],
            mockName: [Function],
            getMockName: [Function] },
         parse: 
          { [Function: parse]
            _isMockFunction: true,
            getMockImplementation: [Function],
            mock: [Getter/Setter],
            mockClear: [Function],
            mockReset: [Function],
            mockRestore: [Function],
            mockReturnValueOnce: [Function],
            mockResolvedValueOnce: [Function],
            mockRejectedValueOnce: [Function],
            mockReturnValue: [Function],
            mockResolvedValue: [Function],
            mockRejectedValue: [Function],
            mockImplementationOnce: [Function],
            mockImplementation: [Function],
            mockReturnThis: [Function],
            mockName: [Function],
            getMockName: [Function] } } }

  console.log src/stackoverflow/56446543/index.ts:5
    { config: [Function: config],
      parse: [Function: parse],
      default: { config: [Function: config], parse: [Function: parse] } }

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.394s, estimated 4s

如您所见, dotenv模块针对第一个测试用例进行了dotenv ,而没有针对第二个测试用例进行dotenv

你可以在这里找到完整的演示: https : //github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56446543

对@slideshowp2 解决方案的改进。

使用jest.domock你需要在模块之后调用require就像这里),但是require的结果是any类型,我们失去了类型安全性。 所以你可以使用打字稿的动态导入

示例完整代码:

import * as summer from './exampleModule';

describe('mock vs no-mock', () => {
    beforeEach(() => {
        jest.resetModules();
    });

    it('NO-MOCKED', async () => {
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(2);
    });
    it('MOCKED', async () => {
        jest.doMock('./exampleModule');
        const summer = await import('./exampleModule');

        const mockedSummer = mocked(summer, true);
        mockedSummer.sum.mockImplementation((a, b) => a + b + 1);
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(3);
    });
    it('NO-MOCKED', async () => {
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(2);
    });
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM