让我们说我在文件customer.ts
中有以下命名的导出
export const saveDetails = ()=>{}
export const loadDetails = ()=>{}
假设我正在其他文件中使用它
import {saveDetails, loadDetails} from './customer.ts'
我想用自定义实现模拟'./customer.ts'。为此,我使用以下代码
const mockSaveDetails = jest.fn().mockImplementation(() => {});
jest.mock('./customer.ts', () => {
return {
saveDetails: mockSaveDetails
};
});
现在,当我运行此代码时,出现以下错误
ReferenceError:初始化前无法访问'mockSaveDetails'
根据https://jestjs.io/docs/en/es6-class-mocks上的文档,我了解到该模拟被提升到顶部,并且例外情况是该变量的前缀为mock
。因此,根据文档,这应该正确吗?如果不是,那么提供带有特定参数的模拟模仿实现并监视这些实现的替代方法(例如,请参阅对saveDetails
的多次调用)。
答案 0 :(得分:4)
ReferenceError:初始化前无法访问'mockSaveDetails'
模拟设置必须是文件中的第一件事,即使在import
之前也是如此。然后mockSaveDetails
将被识别。
如文档所述,它与提升模拟功能有关,但是对于TypeScript来说,这并没有按文档记录完成,因此我们需要一点帮助...
答案 1 :(得分:0)
这是解决方案:
index.ts
:
import { saveDetails, loadDetails } from "./customer";
export function main() {
saveDetails();
loadDetails();
}
customer.ts
:
export const saveDetails = () => {
console.log("real save details");
};
export const loadDetails = () => {
console.log("real load details");
};
index.spec.ts
:
import { main } from "./";
import { saveDetails, loadDetails } from "./customer";
jest.mock("./customer.ts", () => {
return {
saveDetails: jest.fn(),
loadDetails: jest.fn()
};
});
describe("main", () => {
it("should mock correctly", () => {
main();
expect(saveDetails).toBeCalledTimes(1);
expect(loadDetails).toBeCalledTimes(1);
});
});
覆盖率100%的单元测试结果:
PASS src/stackoverflow/59024742/index.spec.ts
main
✓ should mock correctly (5ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.626s, estimated 9s
源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59024742
答案 2 :(得分:0)
如果要为其中一个模拟函数提供实现,则此答案无效。
我发现的唯一解决方案是更改import语句,然后对此使用间谍程序。
customer.ts
const saveDetails = () => {
console.log("real save details");
};
const loadDetails = () => {
console.log("real load details");
};
export { saveDetails, loadDetails }
index.ts
import { saveDetails, loadDetails } from "./customer";
export function main() {
saveDetails();
loadDetails();
}
index.spec.ts
import { main } from ".";
import * as customer from "./customer";
describe("main", () => {
it("should mock correctly", () => {
const detailsSpy = jest.spyOn(customer, 'saveDetails')
.mockImplementation(() => {return {}});
const loadSpy = jest.spyOn(customer, 'loadDetails')
.mockImplementation(() => {return {}});
main();
expect(detailsSpy).toBeCalledTimes(1);
expect(loadSpy).toBeCalledTimes(1);
});
});
答案 3 :(得分:0)
如果你们都想模拟一个命名函数并提供一个实现,你就不需要 import * as
语法。您可以执行以下操作:
// import the named module
import { useWalkthroughAnimations } from '../hooks/useWalkthroughAnimations';
// mock the file and its named export
jest.mock('../hooks/useWalkthroughAnimations', () => ({
useWalkthroughAnimations: jest.fn()
}));
// do whatever you need to do with your mocked function
useWalkthroughAnimations.mockReturnValue({ pageStyles, goToNextPage, page });