如何模拟外部模块方法?

SM7*_*M79 5 javascript unit-testing reactjs jestjs

我有一个带有功能的模块:

const utils = {
  redirectTo(url) {
    if (url) {
      window.location = url;
    }
  },
};

export default utils;
Run Code Online (Sandbox Code Playgroud)

它在React组件的某处使用,如下所示:

import utils from '../../lib/utils';

componentWillUpdate() {
  this.redirectTo('foo')
}
Run Code Online (Sandbox Code Playgroud)

现在,我要检查redirectTo用equals调用的值foo

  it('should redirect if no rights', () => {
    const mockRedirectFn = jest.fn();
    utils.redirectTo = mockRedirectFn;

    mount(
      <SomeComponent />,
    );

    expect(mockRedirectFn).toBeCalled();
    expect(mockRedirectFn).toBeCalledWith('foo');
    console.log(mockRedirectFn.mock);
    // { calls: [], instances: [] }
  });
Run Code Online (Sandbox Code Playgroud)

那就是我所拥有的,它不起作用。我该怎么做呢?

And*_*rle 6

你必须lib/utils像这样模拟模块:

import utils from '../../lib/utils';
jest.mock('../../lib/utils', () => ({
  redirect: jest.fn()
}))

it('should redirect if no rights', () => {
  mount(
    <SomeComponent />,
  );
  expect(utils.redirect).toHaveBeenCalledWith();
});
Run Code Online (Sandbox Code Playgroud)

这将用只返回 .mock 的模拟替换模块{redirect:jest.fn()}。这个模块也被导入到你的测试中,然后你可以访问间谍redirect并测试它是用正确的参数调用的。


SM7*_*M79 5

这就是我最终使用的:

 it('should redirect if no rights', () => {

    // this way we mock only one method: redirectTo
    jest.mock('lib/utils', () => {
      const original = require.requireActual('lib/utils');
      original.default.redirectTo = jest.fn();
      return original;
    });

    const redirectTo = require.requireMock('lib/utils').default.redirectTo;

    mount(
      <SomeComponent />,
    );

    expect(redirectTo).toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)