Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: variable beginning with 'mock' ist NOT hoisted. #3292

Open
ikilinc opened this issue Feb 21, 2022 · 5 comments
Open

[Bug]: variable beginning with 'mock' ist NOT hoisted. #3292

ikilinc opened this issue Feb 21, 2022 · 5 comments
Labels
🐛 Bug Confirmed Bug is confirmed

Comments

@ikilinc
Copy link

ikilinc commented Feb 21, 2022

Version

27.1.3

Steps to reproduce

const mock = jest.fn();
jest.mock('@sailplane/logger', () => {
  const mockLogger = jest.fn().mockImplementation(() => {
    return {
      debugObject: mock,
      debug: jest.fn(),
    };
  });

  return {
    Logger: mockLogger,
  };
});

Expected behavior

Test runs without error.

Actual behavior

throws error.

ReferenceError: Cannot access 'mock' before initialization

Debug log

● Test suite failed to run

ReferenceError: Cannot access 'mock' before initialization

  57 |   const mockLogger = jest.fn().mockImplementation(() => {
  58 |     return {
> 59 |       debugObject: mock,
     |                    ^
  60 |       debug: jest.fn(),
  61 |     };
  62 |   });

Additional context

No response

Environment

System:
    OS: Linux 5.10 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (8) x64 Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
  Binaries:
    Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node
    npm: 8.3.1 - ~/.nvm/versions/node/v16.14.0/bin/npm
@ahnpnl
Copy link
Collaborator

ahnpnl commented Mar 12, 2022

By default, jest.mock always hoists. This is not applied to variables starting with mock. Do you have any references saying that variable starting with mock should be the same?

EDITED: reference link jestjs/jest#8148 (comment)

this is a bug indeed

@smbkr
Copy link

smbkr commented Apr 5, 2022

This was discussed previously in 2020: #1088

Essentially, jest doesn't hoist variables starting with mock, but when hoisting mocked functions during initialisation, does not check if variables starting with mock are accessible when setting up the mocks.

@ahnpnl in the linked issue, you indicated that you were not interested in supporting this in ts-jest. Is this no longer the case? If so, where does this fit on your roadmap, and is any help required with this issue?

It's currently preventing me from migrating my projects from jest+babel to ts-jest. I'm creating mocks in ways like the following:

const mockSSM = {
    getParameter: jest.fn().mockReturnThis(),
    putParameter: jest.fn().mockReturnThis(),
    promise: jest.fn(),
}

jest.mock('aws-sdk', () => ({
    SSM: jest.fn().mockImplementation(() => mockSSM),
}))

@ahnpnl
Copy link
Collaborator

ahnpnl commented Apr 5, 2022

It's not about not interested in supporting this in ts-jest:) This can be achieved via modifying our AST transformer https://github.com/kulshekhar/ts-jest/blob/main/src/transformers/hoist-jest.ts to have this behavior. Any helps are welcome.

@smbkr
Copy link

smbkr commented Apr 6, 2022

Thanks, I've opened a PR #3400 with a failing e2e test, however I'm not entirely sure where to go from here - the tests for the AST transformer seem to already check for this behaviour.

@janeklb
Copy link

janeklb commented Aug 19, 2022

The following is a decent workaround until ts-jest supports this directly (if ever -- im still not sure if it's possible given how this behaviour is achieved in vanilla jest)

The key is to declare the variable using var (not let), and then initialise the value inside the mock factory

// eslint-disable-next-line no-var
var mockThing: jest.Mock;

jest.mock('./path-to/module', () => {
  mockThing = jest.fn();
  return {
    thing: mockThing,
  };
});

// OR more succinctly

jest.mock('./path-to/module', () => ({
  thing: (mockThing = jest.fn()),
}));

then you can do whatever you want in your test / beforeEach functions etc.

beforeEach(() => {
  mockThing.mockRejectedValue(new Error('bang!'));
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 Bug Confirmed Bug is confirmed
Projects
None yet
Development

No branches or pull requests

4 participants