typescript jest引用错误:初始化前无法访问“”

9njqaruj  于 2022-11-18  发布在  TypeScript
关注(0)|答案(7)|浏览(225)

我收到错误:
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()而不是变量时,它就工作了,但是我不确定如何在稍后的测试中使用这些变量。

vh0rcniy

vh0rcniy1#

上面的答案都不能解决我的问题,所以下面是我的解决方案:

var mockMyMethod: jest.Mock;

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

在导入之前使用const让我觉得有些奇怪。问题是:jest.mock被提升。为了能够在它之前使用变量,你需要使用var,因为它也被提升了。它不适用于letconst,因为它们不是。

ohtdti5x

ohtdti5x2#

当您需要监视const声明时,接受的答案不会处理,因为它是在模块工厂范围内定义的。
对我来说,模块工厂需要高于任何导入语句,**最终 * 导入您想要模拟的东西。

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

qlvxas9a3#

要澄清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,
        })
    }
  }
});
iezvtpos

iezvtpos4#

文档解决的问题是jest.mock被提升,但const声明没有被提升。这导致在导入模拟模块时工厂函数被求值,并且变量处于时间死区。
如果需要访问嵌套的模拟函数,则需要将它们作为导出对象的一部分公开:

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

这也适用于__mocks__中的手动模拟,其中变量只能在模拟内部访问。

laximzn5

laximzn55#

你应该把你的嘲笑高于你的进口;这可能是你的问题的根源。进口也是悬挂的,所以多个悬挂的条目会按顺序悬挂。
然而,如果你因为某种原因不能这样做,你可以使用doMock来避免提升行为。如果这发生在你的文件的顶部,它应该是一个1到1的变化。

const mockMyMethod = jest.fn();
jest.doMock('some-package', () => ({ myMethod: mockMyMethod }));
4urapxun

4urapxun6#

这个解决方案对我来说很有效,对vuejs+ jest来说也很容易。
需要注意两点:

  • 您应该声明绝对路径,而不是“@/js/network/repository”
  • getter有助于延迟示例化
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']);
cgh8pdjw

cgh8pdjw7#

将TypeScript与Jest和mockDebug.js模块一起使用的示例

jest.mock('debug', () => {
  global.mockDebug = jest.fn();
  return () => global.mockDebug;
});

// usage
describe('xxx', () => {
    test('xxx', () => {
        expect(global.mockDebug.mock.calls.toString()).toContain('ccc');
    })
});

相关问题