在测试中替换特定模块

Sam*_*Sam 10 javascript fetch ecmascript-6 reactjs jestjs

我正在使用Jest测试我的React-Redux应用程序,并且在我的API调用中,我正在导入一个fetch模块cross-fetch.我想覆盖或替换它fetch-mock.这是我的文件结构:

Action.js

import fetch from 'cross-fetch';
export const apiCall = () => {
    return fetch('http://url');
Run Code Online (Sandbox Code Playgroud)

Action.test.js

import fetchMock from 'fetch-mock';
import { apiCall } from './Action';
fetchMock.get('*', { hello: 'world' });
describe('actions', () => {
    apiCall().then(
        response => {
            console.log(response)
        })
})
Run Code Online (Sandbox Code Playgroud)

显然,此时我还没有设置测试.因为交叉获取是在更接近函数的情况下导入的,所以它使用它的fetch实现,导致它执行实际调用而不是我的模拟.什么是获取被嘲笑的最佳方式(除了删除import fetch from 'cross-fetch'线)?

有没有办法做到这取决于称为节点脚本是否是有条件进口testbuild?或者将模拟的提取设置为优先级?

Cod*_*ice 5

fetch-mock不是要替换fetch()您正在测试的代码中的调用,也不是要更改或删除任何导入.相反,它在您的测试期间提供模拟响应,以便通过fetch()接收已知的可靠响应进行请求.


Syl*_*ain 2

如果你的项目是 webpack 项目,那么https://github.com/ Plasticine/inject-loader非常有用。您只需几行代码即可将任何依赖项与模拟交换。

describe('MyModule', () => {
  let myModule;
  let dependencySpy;

  beforeEach(() => {
    dependencySpy= // {a mock/spy};
    myModule = require('inject-loader!./MyModule')({
      'cross-fetch': {dependencySpy},
    });
  });

  it('should call fetch', () => {
    myModule.function1();
    expect(dependencySpy.calls.length).toBe(1);
  });

});
Run Code Online (Sandbox Code Playgroud)

注意:确保不要在文件顶部导入正在测试的模块。调用require完成了这部分工作。