我收到错误消息:
ReferenceError: Cannot access 'myMock' before initialization
A limitation with the factory parameter is that, since calls to jest.mock() are hoisted to the top of the file, it's not possible to first define a variable and then use it in the factory. An exception is made for variables that start with the word 'mock'.
我在做这个:
import MyClass from './my_class';
import * as anotherClass from './another_class';
const mockMethod1 = jest.fn();
const mockMethod2 = jest.fn();
jest.mock('./my_class', () => {
return {
default: {
staticMethod: jest.fn().mockReturnValue(
{
method1: mockMethod1,
method2: mockMethod2,
})
}
}
});
正如你所看到的,我的两个变量都符合“标准”,但没有正确提升。
我错过了什么吗?
很明显,当我只是通过
jest.fn()
而不是我的变量时它会起作用,但我不确定以后如何在我的测试中使用它们。
上面的答案都没有解决我的问题,所以这是我的解决方案:
var mockMyMethod: jest.Mock;
jest.mock('some-package', () => ({
myMethod: mockMyMethod
}));
我觉得在导入之前使用 const 有点奇怪。事情是:
jest.mock
被吊起。为了能够在它之前使用一个变量,你需要使用var
,因为它也被提升了。它不适用于 let
和 const
因为它们不是。
当您需要监视
const
声明时,接受的答案不会处理,因为它是在模块工厂范围内定义的。
对我来说,模块工厂需要above任何导入语句最终导入你想要模拟的东西。 这是使用 nestjs 和 prisma 库的代码片段。
// app.e2e.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import mockPrismaClient from './utils/mockPrismaClient'; // you can assert, spy, etc. on this object in your test suites.
// must define this above the `AppModule` import, otherwise the ReferenceError is raised.
jest.mock('@prisma/client', () => {
return {
PrismaClient: jest.fn().mockImplementation(() => mockPrismaClient),
};
});
import { AppModule } from './../src/app.module'; // somwhere here, the prisma is imported
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
)};
为了澄清 Jason Limantoro 所说的内容,将
const
移到导入模块的上方:
const mockMethod1 = jest.fn(); // Defined here before import.
const mockMethod2 = jest.fn();
import MyClass from './my_class'; // Imported here.
import * as anotherClass from './another_class';
jest.mock('./my_class', () => {
return {
default: {
staticMethod: jest.fn().mockReturnValue(
{
method1: mockMethod1,
method2: mockMethod2,
})
}
}
});
文档解决的问题是
jest.mock
被提升但 const
声明没有。这导致在导入模拟模块时评估工厂函数,并且变量处于临时死区。
如果有必要访问嵌套的模拟函数,它们需要作为导出对象的一部分公开:
jest.mock('./my_class', () => {
const mockMethod1 = jest.fn();
const mockMethod2 = jest.fn();
return {
__esModule: true,
mockMethod1,
mockMethod2,
default: {
...
这也适用于
__mocks__
中的手动模拟,其中变量只能在模拟中访问。
你应该把你的模拟移到你的导入之上;那可能是您问题的根源。 进口也被吊装,所以多个被吊装的条目将被顺序吊装。
jest.mock('./my_class', () => {
const mockMethod = jest.fn()
const default = { staticMethod: jest.fn().mockReturnValue({ method: mockMethod }) };
return { default, mockMethod };
});
import MyClass, { mockMethod } from './my_class'; // will import your mock
import * as anotherClass from './another_class';
doMock
来避免提升行为。如果这发生在您的文件顶部,则应该是一对一的更改。
const mockMyMethod = jest.fn();
jest.doMock('some-package', () => ({ myMethod: mockMyMethod }));
这个解决方案对我有用,对 vuejs+ jest 来说也很简单。
注意两点:
const mockGetNextStatuses = jest.fn();
const mockUpdatePrintingStatus = jest.fn();
jest.mock('../../../../../../src/js/network/repositories/index.js', () => {
return {
get printing() {
return {
getNextStatuses: mockGetNextStatuses,
updatePrintingStatus: mockUpdatePrintingStatus,
}
}
}
});
或
jest.mock('../../../../../../src/js/network/repositories/index.js', () => ({
printing: {
getNextStatuses: jest.fn(),
updatePrintingStatus: jest.fn()
}
}));
import { printing } from '../../../../../../src/js/network/repositories/index.js';
// and mock the module
printing.getNextStatuses.mockReturnValue(['XX','YY']);
请检查此解决方案:https://www.bam.tech/article/fix-jest-mock-cannot-access-before-initialization-error
我用它来解决同样的问题
Jest 和 mockDebug.js 模块使用 TypeScript 的例子
jest.mock('debug', () => {
global.mockDebug = jest.fn();
return () => global.mockDebug;
});
// usage
describe('xxx', () => {
test('xxx', () => {
expect(global.mockDebug.mock.calls.toString()).toContain('ccc');
})
});