Mock.mockImplementation 失败并显示“不是函数”

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

我有服务班

服务.js

class Service {
}
export default new Service();

我正在尝试为此提供一个模拟实现。如果我使用这样的东西:

jest.mock('./Service', () => { ... my mock stuff });

它工作正常,但是我无法访问在模拟之外声明的任何变量,这有点限制,因为我想重新配置模拟返回的内容等。

我尝试了这个(受到另一篇 StackOverflow 文章的启发:用 Jest 模拟的服务会导致“不允许 jest.mock() 的模块工厂引用任何超出范围的变量”错误

import service from './Service';

jest.mock('./Service', () => jest.fn);

service.mockImplementation(() => {
    return { ... mock stuff }
);

不幸的是,当我尝试运行此程序时,出现以下错误:

TypeError: _Service2.default.mockImplementation is not a function
jestjs
9个回答
53
投票

我和@Janos有同样的问题,其他答案也没有帮助。你可以做两件事:

  1. 如果您只需要模拟 Service 中的一个函数,请在测试文件中:

    import service from './Service';
    
    jest.mock('./Service', () => jest.fn());
    
    service.yourFunction = jest.fn(() => { /*your mock*/ })
    

     

  2. 如果您需要模拟整个模块:

    假设你的service.js在javascript/utils中,创建一个javascript/utils/_mocks_并在其中创建一个service.js文件,然后你可以在这个文件中模拟整个类,例如:

    const myObj = {foo: "bar"}
    
    const myFunction1 = jest.fn(() => { return Promise.resolve(myObj) })
    
    const  myFunction2 = ...
    
    module.exports = {
      myFunction1,
      myFunction2
    }
    

    然后在您的测试文件中添加:

    jest.mock('./javascript/utils/service')
    

    ...从模拟文件导出的函数将通过您的测试文件执行被命中。


19
投票

mock 等于 jest.fn。您需要调用 jest.fn 来创建模拟函数。

所以这个:

jest.mock('./Service', () => jest.fn);

应该是:

jest.mock('./Service', () => jest.fn());

13
投票

遇到类似问题并通过使用

.mockImplementationOnce

解决了它
jest.mock('./Service', () => jest.fn()
  .mockImplementationOnce(() => {
    return { ... mock stuff }
  })
  .mockImplementationOnce(() => {
    return { ... mock other stuff }
  })
);

现在,当您运行另一个测试时,它将返回第二个模拟对象。


5
投票

您需要将模拟组件存储在名称以“mock”为前缀的变量中,并确保在从“main.js”文件中的默认值导入服务时返回具有默认属性的对象。

// Service.js
class Service {
}
export default new Service();

// main.test.js (main.js contains "import Service from './Service';")

const mockService = () => jest.fn();

jest.mock('./Service', () => {
    return {
        default: mockService
    }
});

1
投票

我的错误是我在每次测试之前重置模拟。 如果您这样做,请务必重新配置模拟实现。

例如,更改此:

  let value;
  let onPropertyChange: OnPropertyChangeCallback = jest.fn((changes: any) => {
      value = changes["testValue"];
    });

  const user = userEvent.setup();

  beforeEach(() => {
    jest.resetAllMocks();
  });

对此:

  let value;
  let onPropertyChange: OnPropertyChangeCallback;

  const user = userEvent.setup();

  beforeEach(() => {
    jest.resetAllMocks();

    onPropertyChange = jest.fn((changes: any) => {
      value = changes["testValue"];
    });
  });

0
投票

我有类似的问题,原因是“.spec.js”文件有一个

import jest from "jest-mock";

删除此行后,它起作用了。


0
投票

在我的例子中mockImplementation不起作用,因为我复制粘贴测试并忘记在这个地方删除“async”关键字

it('test description', **async** () => {...}


0
投票

我的文件没有默认导出,而是有各种其他导出,我需要模拟其中之一。这最终对我有用:

// services.test.js
const services = require('./services');

...

const innerFunction = jest.fn(() => console.log("calling innerFunction"));
services.functionToMock = jest.fn(() => ({innerFunction}))

后来我能够测试我的

innerFunction
是否被正确调用了

...
expect(innerFunction).toHaveBeenCalledTimes(1);

-2
投票

从测试中删除异步并且不要等待!

错误

it.only('throws error on private visibility', async () => {
    await expect(getSteamData(mockSteamId)).rejects.toThrow(ErrorMessage.PRIVATE_VISIBILITY);
  });

it.only('throws error on private visibility', () => {
     expect(getSteamData(mockSteamId)).rejects.toThrow(ErrorMessage.PRIVATE_VISIBILITY);
  });
© www.soinside.com 2019 - 2024. All rights reserved.