如何使用 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 模拟此动态导入的成功和失败承诺案例,以确保在解析或失败时分别调用每个方法(successMethod
和 errorMethod
)?
我发现 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();
});
所以我一直在为如何测试动态导入而苦苦挣扎,在这种情况下,尤其是开玩笑,我在互联网上阅读了很多但没有找到任何具体的内容,所以我考虑提出这个问题集中一个体面的解决方案。
我在 class
中有以下方法class MyClass {
successMethod() { ... }
errorMethod() { ... }
myMethod() {
return import('./myFile.js')
.then(() => this.successMethod())
.catch(() => this.errorMethod());
}
}
我的问题是:
如何使用 Jest 模拟此动态导入的成功和失败承诺案例,以确保在解析或失败时分别调用每个方法(successMethod
和 errorMethod
)?
我发现 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();
});