为什么我不能在jest.Mock中模拟一个函数(必须在spyOn上使用.mockImplementation)?

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

我期望当我使用jest.mock()模拟一个模块并将函数实现传递给每个对象时,它们会继续进行测试。

import * as services from '_services';

// I thought this would be enough to mock 'load_basket'
jest.mock('_services', () => ({
  load_basket: jest.fn(() => Promise.resolve([]))
}));

describe('WB Component', () => {
  it('loads basket if basket prop is null', () => {

    // However, if I don't use .mockImplemenation here it gives
    // me an error that load_basket wasn't called
    const spy = spyOn(services, 'load_basket').mockImplementation(() => Promise.resolve([]));
    const wrapper = shallow(<WB basket={null} />);
    expect(spy).toHaveBeenCalled();
    wrapper.unmount();
    spy.mockRestore();
  });
});

但我可以删除.mock中的函数实现,只有load_basket: jest.fn(),但我不能删除底部的.mockImplementation(() => Promise.resolve([]))或我会得到expected spy to have been called, but it was not called

编辑:如果我在原始的.mock调用或.mockImplementation中既没有函数实现,它也会给我一个TypeError: Cannot read property 'then' of undefined ... load_basket是'undefined'。这对我来说很有意义,但我仍然不明白为什么在.mock中嘲弄这个函数会使它与测试中的间谍函数不同?

Edit2:load_basket以下列方式使用

class WB extends Component {
  constructor(props) {
    super(props);
    this.state = {
      basket: props.basket,
      loading_basket: !props.basket,
    };
  }

  componentDidMount(): void {
    if (!this.state.basket) {
      load_basket()
        .then(res => {
          this.setState({
            basket: res,
            loading_basket: false
          });
        })
        .catch( ... );
    }
  }

  render () { ... }
}
unit-testing jestjs enzyme
1个回答
0
投票

jest.mock接受一个可选的factory参数,如果提供了一个,那么module将替换为调用factory参数的结果。

因此,当你的测试函数被调用时,services.load_basket已经是一个mock function了。


错误详情

你正在调用spyOn,最终调用undocumented legacy Jasmine spyOn functionJest基于Jasmine),我猜你打算打电话给jest.spyOn

来自spyOnJasmine函数与Jest模拟函数无​​法正常工作,如果您还没有模拟实现,最终会导致您看到的错误。

请注意,如果你调用了jest.spyOn它只会return the existing mock function,因为load_basket已经是一个模拟函数,它可以在没有模拟实现的情况下工作。


尽管如此,你不需要监视services.load_basket,因为它已经是一个模拟函数。

您的测试可以简化为:

import * as services from '_services';

jest.mock('_services', () => ({
  load_basket: jest.fn(() => Promise.resolve([]))
}));

describe('WB Component', () => {
  it('loads basket if basket prop is null', () => {
    const wrapper = shallow(<WB basket={null} />);
    expect(services.load_basket).toHaveBeenCalled();  // Success!
  });
});
© www.soinside.com 2019 - 2024. All rights reserved.