jest ReferenceError: Cannot access '' before initialization

问题描述 投票:0回答:8

我收到错误消息:

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()
而不是我的变量时它会起作用,但我不确定以后如何在我的测试中使用它们。

javascript node.js typescript unit-testing jestjs
8个回答
39
投票

上面的答案都没有解决我的问题,所以这是我的解决方案:

var mockMyMethod: jest.Mock;

jest.mock('some-package', () => ({
  myMethod: mockMyMethod
}));

我觉得在导入之前使用 const 有点奇怪。事情是:

jest.mock
被吊起。为了能够在它之前使用一个变量,你需要使用
var
,因为它也被提升了。它不适用于
let
const
因为它们不是。


21
投票

当您需要监视

const
声明时,接受的答案不会处理,因为它是在模块工厂范围内定义的。

对我来说,模块工厂需要above任何导入语句最终导入你想要模拟的东西。 这是使用 nestjsprisma 库的代码片段。

// 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();
  });
)};

18
投票

为了澄清 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,
        })
    }
  }
});

9
投票

文档解决的问题是

jest.mock
被提升但
const
声明没有。这导致在导入模拟模块时评估工厂函数,并且变量处于临时死区。

如果有必要访问嵌套的模拟函数,它们需要作为导出对象的一部分公开:

jest.mock('./my_class', () => {
  const mockMethod1 = jest.fn();
  const mockMethod2 = jest.fn();
  return {
    __esModule: true,
    mockMethod1,
    mockMethod2,
    default: {
      ...

这也适用于

__mocks__
中的手动模拟,其中变量只能在模拟中访问。


7
投票

你应该把你的模拟移到你的导入之上;那可能是您问题的根源。 进口也被吊装,所以多个被吊装的条目将被顺序吊装。

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 }));

0
投票

这个解决方案对我有用,对 vuejs+ jest 来说也很简单。

注意两点:

  • 你应该声明绝对路径而不是'@/js/network/repositories'
  • 吸气剂有助于推迟实例化
    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']);

-1
投票

请检查此解决方案:https://www.bam.tech/article/fix-jest-mock-cannot-access-before-initialization-error

我用它来解决同样的问题


-2
投票

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');
    })
});
© www.soinside.com 2019 - 2024. All rights reserved.