如何使用 Jest 监视默认导出函数?

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

假设我有一个导出默认函数的简单文件:

// UniqueIdGenerator.js
const uniqueIdGenerator = () => Math.random().toString(36).substring(2, 8);

export default uniqueIdGenerator;

我会这样使用:

import uniqueIdGenerator from './UniqueIdGenerator';
// ...
uniqueIdGenerator();

我想在我的测试中断言调用此方法时会保留原始功能。我会使用

jest.spyOn
来做到这一点,但是它需要一个对象以及一个函数名称作为参数。如何以干净的方式做到这一点?对于任何感兴趣的人来说,jasmine有一个类似的
GitHub问题

reactjs unit-testing mocking jestjs spy
10个回答
108
投票

我最终放弃了默认导出:

// UniqueIdGenerator.js
export const uniqueIdGenerator = () => Math.random().toString(36).substring(2, 8);

然后我可以像这样使用和监视它:

import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'uniqueIdGenerator');

有些人建议将它们包装在 const 对象中,然后将其导出。我想你也可以使用类来包装。

但是,如果您无法修改类,仍然有一个(不太好的)解决方案:

import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'default');

44
投票

这是一种默认导出的方法,无需修改导入(甚至在测试中根本不需要导入):

const actual = jest.requireActual("./UniqueIdGenerator");
const spy = jest.spyOn(actual, "default");

31
投票

还可以模拟导入并将原始实现作为模拟实现传递,例如:

import uniqueIdGenerator from './UniqueIdGenerator'; // this import is a mock already

jest.mock('./UniqueIdGenerator.js', () => {
  const original = jest.requireActual('./UniqueIdGenerator')
  return {
     __esModule: true,
     default: jest.fn(original.default)
  }
})

test(() => {
  expect(uniqueIdGenerator).toHaveBeenCalled()
})

14
投票

在某些情况下,您必须模拟导入才能监视默认导出:

import * as fetch from 'node-fetch'

jest.mock('node-fetch', () => ({
  default: jest.fn(),
}))

jest.spyOn(fetch, 'default')

13
投票

使用“default”作为spyOn函数中的第二个参数。

import * as MyHelperMethod from '../myHelperMethod';

jest.spyOn(MyHelperMethod, 'default');

11
投票

仅模拟默认导出或任何其他导出,但将模块中的剩余导出保留为原始导出:

import myDefault, { myFunc, notMocked } from "./myModule";

jest.mock("./myModule", () => {
  const original = jest.requireActual("./myModule");
  return {
    __esModule: true,
    ...original,
    default: jest.fn(),
    myFunc: jest.fn()
  }
});

describe('my description', () => {
  it('my test', () => {
    myFunc();
    myDefault();
    expect(myFunct).toHaveBeenCalled();
    expect(myDefault).toHaveBeenCalled();
    
    myDefault.mockImplementation(() => 5);
    expect(myDefault()).toBe(5);
    expect(notMocked()).toBe("i'm not mocked!");
  })
});

5
投票

对我有用的是Janne Annala的答案和OP自己的解决方案的结合。我想要测试的只是使用正确的参数调用辅助方法,因为我已经为辅助方法编写了测试,并且它对我后续的测试没有任何影响:

// myHelperMethod.js

export const myHelperMethod = (param1, param2) => { // do something with the params };
// someOtherFileUsingMyHelperMethod.js

import * as MyHelperMethod from '../myHelperMethod';


jest.mock('../myHelperMethod', () => ({
  myHelperMethod: jest.fn(),
}));

let myHelperMethodSpy = jest.spyOn(MyHelperMethod, 'myHelperMethod');

// ...
// some setup
// ...

test(() => {
  expect(myHelperMethodSpy).toHaveBeenCalledWith(param1, param2);
});

1
投票

这里就更简单了。

使用

sleep
模拟导出的模块“addDelay”(其中包含
jest
函数)。

const { sleep } = require('../../src/utils/addDelay');

jest.mock('../../src/utils/addDelay', () => {
const delay = jest.requireActual('../../src/utils/addDelay');
return {
  ...delay,
  sleep: jest.fn(),
};});

测试如下,检查

sleep
函数是否像 arg 中那样在 1 秒内调用。

test("Should delay 1 second if Okta user has no IDxM Roles", async () => {
    // GIVEN
    const MockSleep = sleep;

    // WHEN
    await getUser(req, res);
    
    // THEN
    expect(MockSleep).toHaveBeenCalledWith(1000);// sleep(1000): 1sec
});

1
投票

我知道我参加聚会迟到了,但我最近遇到了这个问题,也想分享我的解决方案......虽然它看起来有点不传统,但可以由有更多知识的人进行调整。

我碰巧有一个具有我想要监视的功能的文件。

// /foo/ModuleToBeMocked.ts
const fnToSpyOn = () => ...;

export default { fnToSpyOn }

然后将其导入到父文件中,该文件将带来和导出类似的功能。有点像分类。

// /parent.ts
import fnToSpyOn from './foo/ModuleToBeMocked';
import someOtherFn from './foo/SomeOtherModule';
...

export { fnToSpyOn, someOtherFn, ... };

这就是我测试

fnToSpyOn

的方式
// /foo/ModuleToBeMocked.test.ts
import { ModuleToBeMocked } from '../parent';

const fnToSpyOnSpu = jest.spyOn(ModuleToBeMocked, 'fnToSpyOn');

0
投票

用户的解决方案thisismydesign(第一个答案)对我不起作用。我做了一些修改才能开始工作。

首先,我导出了一个默认对象:

// UniqueIdGenerator.js
const uniqueIdGenerator = () => Math.random().toString(36).substring(2, 8);
export default {uniqueIdGenerator}

为了使用它,我做了如下操作:

import generator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(generator, 'uniqueIdGenerator');
© www.soinside.com 2019 - 2024. All rights reserved.