Búsqueda de sitios web

javascript - jest ReferenceError: No se puede acceder a '' antes de la inicialización


Estoy recibiendo el error:

ReferenceError: Cannot access 'myMock' before initialization

Aunque respeté la documentación de Jest sobre el hoisting: Una limitación con el parámetro de la fábrica es que, debido a que las llamadas a jest.mock() se elevan al inicio del archivo, no es posible definir primero una variable y luego usarla en la fábrica. Se hace una excepción para las variables que comienzan con la palabra 'mock'.

Estoy haciendo esto:

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

como puedes ver, ambas de mis variables respetan el "estándar" pero no se elevan correctamente.

¿Me estoy perdiendo de algo?

Obviamente funciona cuando simplemente paso jest.fn() en lugar de mis variables, pero no estoy seguro de cómo poder usar estas en mi prueba más adelante.

Respuesta #1

Ninguna de las respuestas anteriores resolvió mi problema, así que aquí está mi solución:

const mockMyMethod = jest.fn();

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

EDITAR

La solución anterior usaba elevar el var, pero eso es un arreglo extraño. La solución actualizada lo hace sin elevar de una manera que hace feliz a jest. Funciona porque la función mockMyMethod no se ejecuta realmente hasta que se llama al método myMethod desde el paquete simulado.

Respuesta #2

La respuesta aceptada no maneja cuando necesitas espiar la declaración const, ya que está definida dentro del alcance de la fábrica del módulo.

Para mí, la fábrica de módulos debe estar antes de cualquier declaración de importación que eventualmente importe la cosa que deseas simular. Aquí hay un fragmento de código usando NestJS con la biblioteca 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();
  });
)};

Respuesta #3

Para aclarar lo que dijo Jason Limantoro, mueve el const arriba de donde se importa el módulo:

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

Respuesta #4

Deberías mover tus burlas por encima de tus importaciones; eso podría ser la fuente de tu problema. Las importaciones también se elevan, por lo que múltiples entradas elevadas se elevarían en orden.

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';

Sin embargo, si por alguna razón no puedes hacer eso, podrías usar doMock para evitar el comportamiento de elevación. Si esto ocurre al principio de tu archivo, debería ser un cambio 1 a 1.

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

También recomiendo usar var en lugar de const o let para mocks. Su comportamiento de hoisting es ligeramente diferente, y he descubierto en varias ocasiones que usar var parece funcionar mejor con el hoisting propio de jest.

Respuesta #5

El problema que aborda la documentación es que jest.mock se eleva, pero la declaración const no lo hace. Esto resulta en que la función de fábrica se evalúe en el momento en que se importa el módulo simulado y una variable se encuentre en la zona muerta temporal.

Si es necesario acceder a funciones simuladas anidadas, deben exponerse como parte del objeto de exportación:

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

Esto también se aplica a los mocks manuales en __mocks__ donde las variables son accesibles solo dentro de un mock.

Artículos relacionados