如何使用 Jest 测试动态导入(then 和 catch)

How to test dynamic imports (then and catch) with Jest

所以我一直在为如何测试动态导入而苦苦挣扎,在这种情况下,尤其是开玩笑,我在互联网上阅读了很多但没有找到任何具体的内容,所以我考虑提出这个问题集中一个体面的解决方案。

我在 class

中有以下方法
class MyClass {
   successMethod() {  ...  }

   errorMethod() { ... }

    myMethod() {
        return import('./myFile.js')
           .then(() => this.successMethod())
           .catch(() => this.errorMethod());
    }
}

我的问题是:

如何使用 Jest 模拟此动态导入的成功和失败承诺案例,以确保在解析或失败时分别调用每个方法(successMethoderrorMethod)?

我发现 jest.doMock 有助于模拟已解决的案例,但没有找到通过模拟它使动态导入失败的方法,因此 catch 案例未被发现。

注意:这不是 React 应用程序,这是一个 Vanilla JS 项目。

可能是

beforeEach(() => {
  jest.resetModules();
});
beforeAll(() => {
  MyClass.mockImplementation(() => {
    return {
      successMethod: () => {
        console.log("succees");
      },
      errorMethod: () => {
        console.log("error");
      }
    };
  });
});

test("should fail", () => {
  jest.doMock("./myFile.js", () => {
    return jest.fn(() => {
      throw new Error("Parameter is not a number!");
    });
  });
  const kls = MyClass();
  kls.myMethod();
  expect(kls.errorMethod).toHaveBeenCalledTimes(1);
  expect(kls.successMethod).toHaveBeenCalledTimes(0);
});
test("should pass", () => {
  jest.doMock("./myFile.js", () => {
    return jest.fn(() => 1);
  });
  const kls = MyClass();
  kls.myMethod();
  expect(kls.errorMethod).toHaveBeenCalledTimes(0);
  expect(kls.successMethod).toHaveBeenCalledTimes(1);
});

可以在 MyClass.prototype 或 class 实例上监视或模拟原型方法。应为每个测试恢复模块模拟和间谍功能,以便它们不会相互影响。

let myClass;
beforeEach(() => {
  jest.resetModules();
  jest.restoreAllMocks();
  myClass = new MyClass();
  jest.spyOn(myClass, 'successMethod');
  jest.spyOn(myClass, 'errorMethod');
});

jest.doMock 要求在调用后导入所有受影响的模块。为了动态 import 导致被拒绝的承诺,myFile 模块应该在评估时抛出错误。由于动态 import returns 承诺,测试应该是异步的。

it('...', async () => {
  jest.mock('./myFile.js', () => 'value');
  await expect(myClass.myMethod()).resolves.toEqual(/* return value from successMethod */);
  expect(myClass.successMethod).toBeCalled();
  expect(myClass.errorMethod).not.toBeCalled();
});

it('...', async () => {
  jest.mock('./myFile.js', () => { throw new Error() });
  await expect(myClass.myMethod()).rejects.toThrow(/* error message from errorMethod */);
  expect(myClass.successMethod).not.toBeCalled();
  expect(myClass.errorMethod).toBeCalled();
});