Cannot access before initialization js ошибка

None of the answers above solved my problem, so here’s my solution:

var mockMyMethod: jest.Mock;

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

Something about using const before the imports feels weird to me. The thing is: jest.mock is hoisted. To be able to use a variable before it you need to use var, because it is hoisted as well. It doesn’t work with let and const because they aren’t.

answered Jun 21, 2021 at 19:31

Mauro Vinicius's user avatar

4

The accepted answer does not handle when you need to spy on the const declaration, as it is defined inside the module factory scope.

For me, the module factory needs to be above any import statement that eventually imports the thing you want to mock.
Here is a code snippet using a nestjs with prisma library.

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

answered Apr 15, 2021 at 19:07

Jason's user avatar

JasonJason

2744 silver badges5 bronze badges

3

To clarify what Jason Limantoro said, move the const above where the module is imported:

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

answered May 19, 2021 at 0:49

Matt's user avatar

MattMatt

4,1814 gold badges38 silver badges56 bronze badges

The problem that the documentation addresses is that jest.mock is hoisted but const declaration is not. This results in factory function being evaluated at the time when mocked module is imported and a variable being in temporal dead zone.

If it’s necessary to access nested mocked functions, they need to be exposed as a part of export object:

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

This also applies to manual mocks in __mocks__ where variables are accessible inside a mock only.

answered Jan 4, 2021 at 7:43

Estus Flask's user avatar

Estus FlaskEstus Flask

203k70 gold badges416 silver badges556 bronze badges

5

You should move your mocking above your imports; that could be the source of your issue. Imports are also hoisted, so multiple hoisted entries would be hoisted in order.

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

However, if you for some reason can’t do that, you could use doMock to avoid hoisting behaviour. If this happens on the top of your file, it should be a 1 to 1 change.

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

answered Aug 1, 2022 at 3:57

Ricardo Nolde's user avatar

Ricardo NoldeRicardo Nolde

33.2k4 gold badges36 silver badges39 bronze badges

1

This solution works for me and it’s pretty easy for vuejs+ jest.

Two points to note:

  • you should declare the absolute path and not ‘@/js/network/repositories’
  • the getter helps to defer the instantiation
    const mockGetNextStatuses = jest.fn();
    const mockUpdatePrintingStatus = jest.fn();
    
    jest.mock('../../../../../../src/js/network/repositories/index.js', () => {
        return {
            get printing() {
                return {
                    getNextStatuses: mockGetNextStatuses,
                    updatePrintingStatus: mockUpdatePrintingStatus,
                }
            }
        }
    });

or

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

answered Aug 12, 2022 at 12:33

Xavier DEJONGHE's user avatar

Per this article… Anyone making it to this page may just be able to set the mocked function to a function returning a function call. As per the OP’s code:

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(), // <- function returning function call
          method2: () => mockMethod2(),
        })
    }
  }
});

answered Apr 5 at 15:14

daleyjem's user avatar

daleyjemdaleyjem

2,2951 gold badge23 silver badges34 bronze badges

This solution worked for me:

jest.mock("../user/useCases/GetUserBalancesUseCase.js", () => {
  return {
    GetUserBalancesUseCase: {
      create: jest.fn().mockReturnValue({
        execute: jest
          .fn()
          .mockReturnValue(require("./fixtures/user/useCaseResponse.js").useCaseResponse),
      }),
    },
  }
})

I couldn’t use the fixture importing it using ESM syntax in this implementation. So I tried using require and fixed the import reference error issue.

This kind of mocking though, is not reliable because bypasses some logic that I want to have covered by the unit test. In my case is necessary to avoid interacting with the infrastructure.

As a reference, I need to test the output of an useCase given an input:

test("Get User Balances", async () => {
    const useCaseResponse = await getUserBalancesUseCase.execute({ account, USDPrices })
    expect(useCaseResponse).toEqual(getUserBalancesUseCaseResponse)
  })

answered Apr 28 at 14:12

d4vecarter's user avatar

Example of using TypeScript with Jest and mockDebug.js module

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

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

node_modules's user avatar

node_modules

4,7406 gold badges21 silver badges37 bronze badges

answered Nov 9, 2022 at 15:17

skypesky's user avatar

1

The “cannot access before initialization” reference error occurs in JavaScript when you try to access a variable before it is declared with let or const and initialized in the same scope. To fix it, initialize the variables before accessing them.

The "cannot access before initialization" reference error occurring in JavaScript.

The “cannot access before initialization” reference error occurring in JavaScript.

Here are some examples of the error occurring:

// ❌ ReferenceError: Cannot access 'num' before initialization console.log(num); let num = 2; // ❌ ReferenceError: Cannot access 'name' before initialization console.log(name); const name = 'Coding Beauty'; // ❌ ReferenceError: Cannot access 'arr' before initialization arr = [7, 8, 9]; let arr = [3, 4, 5]; 

To solve the error, you need to initialize the variable before accessing it.

// ✅ No error let num = 2; console.log(num); // 2 // ✅ No error const name = 'Coding Beauty'; console.log(name); // Coding Beauty // ✅ No error let arr = [3, 4, 5]; arr = [7, 8, 9];

var vs let

The occurrence of this error shows an important difference between the var and let keywords. If you had declared the variable with var, the error wouldn’t have occurred.

// No error console.log(num); // undefined var num = 2; // No error console.log(name); // undefined var name = 'Coding Beauty'; // No error arr = [7, 8, 9]; var arr = [3, 4, 5];

This happens because variables declared with the var keyword are hoisted – they are moved by the JavaScript interpreter to the top of the current scope (to the top of the current script or current function).

Basically, this is what happens to our variables declared with var:

var num; var name; var arr; console.log(num); // undefined num = 2; console.log(name); // undefined name = 'Coding Beauty'; arr = [7, 8, 9]; arr = [3, 4, 5];

Note: The declarations are hoisted, but the initializations are not.

Because of this hoisting, even when the variable is declared in a non-function block, like an if block, the error will still not occur if you try to access the variable from outside the if statement.

// No error! console.log(num); // undefined if (true) { var num = 2; }

Only the global scope and function scopes are used for hoisting, so like before, the variable declaration is moved to the top of the file.

var num; console.log(num); // undefined if (true) { num = 2; }

Every Crazy Thing JavaScript Does

A captivating guide to the subtle caveats and lesser-known parts of JavaScript.

Every Crazy Thing JavaScript Does

Sign up and receive a free copy immediately.

Ayibatari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

Добрый день. Использую webpack+babel+vue.
У меня 2 файла app.js и methods.js
app.js содержит объект Vue и константу с объектом.

import {VUE_METHODS} from 'methods';

export const NDS = {
    title: 'НДС 20%'
};

VUE_METHODS.methods.objectFreeze(NDS);

export let app = new Vue({
    el      : '#app',
    mixins  : [VUE_METHODS],
    //бла бла бла дальше не важно
});

methods.js содержит примесь

import axios from 'axios';
import {NDS} from 'app';

export const VUE_METHODS = {
    data    : function () {
        return {
            nds: NDS
        }
    },
    computed: {
       //бла бла бла
    },
    methods : {
        objectFreeze         : function (_o, _property = null) {
            //не важно
        }
    }
};

В файле сборки вызываю их так

import 'methods';
import 'app';

Все компилится но в браузере при использовании скомпилиного файла вылетает в консоли ошибка

Uncaught ReferenceError: Cannot access 'ne' before initialization

, где ne — это VUE_METHODS. А ругается на строке с
VUE_METHODS.methods.objectFreeze(NDS);

Как решить ошибку?

Comments

@edikdeisling


3 similar comments


1 similar comment

This was referenced

Dec 14, 2022

This was referenced

Mar 30, 2023

hyperupcall

added a commit
to fox-forks/OED
that referenced
this issue

Apr 3, 2023

@hyperupcall

Vite is more strict the `import`s it accepts. These imports are fixed.

Additionally, the Redux store is now exported form a separate file
(other than `index.tsx`. This was done to workaround
vitejs/vite#3033. The circular imports and
Redux store don't play nice, so the circular import was removed.

@hyf0
hyf0

linked a pull request

Apr 27, 2023

that will
close
this issue

9 tasks

hyperupcall

added a commit
to hyperupcall/OED
that referenced
this issue

May 19, 2023

@hyperupcall

Defining the Redux store in the same file as the app creates problems
with Vite. There is some issue with circular imports not working
properly with HMR (hot module replacement). Upstream tracks this issue
at vitejs/vite#3033; a workaround is to define and export the Redux
store from a different file. This commit does exactly that to circumvent
the circular import issue.

In this article, we will delve into the intricacies of a common JavaScript error known as “ReferenceError: Cannot Access Before Initialization.”

We will explore the reasons behind this error and provide comprehensive solutions to help you resolve it effectively.

The “ReferenceError: Cannot access before initialization” error happens when a variable declared with let or const is accessed before it has been initialized within the scope.

Here is how this error occurs:

// 📌 ReferenceError: Cannot access 'arr' before initialization
arr = [3, 2, 1];
let arr = [1, 2, 3];

if (5 === 5) {
  // 📌ReferenceError:
  console.log(num);
  const num = 100;
}

function example() {
  // 📌ReferenceError:
  console.log(str);

  let str = 'bobbyhadz.com';
}

// 📌ReferenceError:
const result = sum(5, 10);

const sum = (a, b) => {
  return a + b;
};

Potential causes of Referenceerror

A common reason for this error is connected to the variable scope.

When you use the let or const keywords to declare a variable inside a block or function, it becomes scoped to that block or function.

Thus, if you attempt to access the variable before declaring it within that scope, the error occurs.

Furthermore, in asynchronous JavaScript, like promises or async/await, the execution order can differ.

If you try to access a variable or function that depends on asynchronous operations before it’s initialized or resolved, an error may occur.

Meanwhile, in JavaScript, “hoisting” is when variable and function declarations are moved to the top during compilation.

Wherein Declarations are hoisted, but not initialization.

In addition, trying to access a variable before declaring it, even with hoisting, results in a “ReferenceError: Cannot Access Before Initialization” error.

Solutions – Referenceerror cannot access before initialization

Initialize the variable before accessing it

The first way to resolve the error is to make sure to initialize the variables before utilizing them.

// 📌 use the let keyword before accessing the variable
let arr = [10, 20, 30];
arr = [30, 20, 10];

if (10 === 10) {
  // 📌 use the const keyword before accessing the variable
  const num = 200;
  console.log(num);
}

function example() {
  // 📌 use the let keyword before accessing the variable
  let str = 'itsourcecode.com';
  console.log(str);
}

// 📌 Define a function with the function keyword instead
const result = sum(10, 20);
console.log(result); // 30

function sum(a, b) {
  return a + b;
}

Variables declared with the keywords “let” and “const” are limited to the scope in which they are declared.

If you’re having trouble pinpointing the location of the error in your code, check the error message displayed in your browser’s console or Node.js terminal.

Move the variable declaration to the top

Another way to solve the error is to move the variable declaration to the top of the if block.

Here is how the error occurs:

const arr = ['car', 'ren', 'bea'];

if ('hi'.length === 2) {
  // 📌 ReferenceError: Cannot access 'arr' before initialization
  arr.push('test');

  const arr = [10, 20, 30];
}

On line 1, we initialized the variable arr and attempted to add a value to the array within the if statement.

Unfortunately, there is a conflicting declaration of arr within the if block, resulting in an error.

The line arr.push(‘test’) in the if block is intended to add a value to the numeric array specifically declared within the if block.

To fix this we have to move the variable declaration to the top of the if block.

const arr = ['car', 'ren', 'bea'];

if ('hi'.length === 2) {
  // 📌️ first declare the variable
  const arr = [10, 20, 30];

  // 📌️ access variable after
  arr.push('test');

  console.log(arr);
}

console.log(arr);

We resolved the problem by declaring the variable arr at the beginning of the if block.

It’s important to note that declaring a variable with the same name as one in the outer scope is generally discouraged.

Leverage Hoisting

While hoisting can be a source of errors, it can also be utilized to your advantage.

By declaring your variables and functions at the top of their respective scopes, you can leverage hoisting effectively and avoid encountering the “ReferenceError: Cannot Access Before Initialization” error.

// Good practice: Utilize hoisting by declaring variables at the top
function myFunction() {
  let myVariable; // Declaration
  // ... Code that uses myVariable ...
  myVariable = 'Initialized'; // Initialization
}

Handle Asynchronous Operations Carefully

When dealing with asynchronous JavaScript, it is crucial to handle the order of execution properly.

Ensure that any dependent variables or functions are fully initialized or resolved before attempting to access them.

// Example: Handling asynchronous operations with Promises
function getData() {
  return new Promise((resolve, reject) => {
    // Simulating an asynchronous operation
    setTimeout(() => {
      const data = 'Initialized';
      resolve(data); // Resolve the Promise
    }, 1000);
  });
}

// Usage of the asynchronous function
async function myFunction() {
  const myData = await getData(); // Wait for data initialization
  // ... Code that uses myData ...
}

Anyway besides this error, we also have here fixed errors that might help you when you encounter them.

  • Uncaught referenceerror google is not defined
  • Importerror: cannot import name ‘parse_rule’ from ‘werkzeug.routing’

Conclusion

In conclusion, the “ReferenceError: Cannot Access Before Initialization” error can be resolved by understanding the underlying causes and applying the appropriate solutions.

By following best practices such as declaring variables at the beginning of their respective scopes, leveraging hoisting effectively, and handling asynchronous operations carefully, you can ensure seamless execution of your JavaScript code.

I think that’s all for this error. I hope you have gained something to fix their issues.

Until next time! 😊

Понравилась статья? Поделить с друзьями:
  • Candy сушилка коды ошибок
  • Candy grand vita ошибка е02
  • Candy стиральные машины ошибка е03 как устранить
  • Candy grand vita ошибка e22
  • Candy стиральные машины ошибка e03 как исправить