jest icon indicating copy to clipboard operation
jest copied to clipboard

Mocking not working

Open swissspidy opened this issue 3 years ago • 31 comments

When using @swc/jest as described in the readme for transforms in Jest tests, I can't seem to use any mocking.

With a test like this:

import got from 'got';

jest.mock('got');

describe('My Test', () => {
  // ...
});

I will get:

TypeError: _got.default.mockImplementationOnce is not a function

Moving the jest.mock() call to the top of the test file also doesn't work.

Any advice appreciated.

swissspidy avatar Aug 12 '21 10:08 swissspidy

Same. By design jest.mock() is hoisting over import. Also other methods should hoist ['mock', 'unmock', 'enableAutomock', 'disableAutomock', 'deepUnmock']

https://github.com/kulshekhar/ts-jest/blob/master/src/transformers/hoist-jest.ts

unlight avatar Aug 30 '21 20:08 unlight

for us mocking stopped working once we added "runtime": "automatic"

chyzwar avatar Oct 15 '21 08:10 chyzwar

Our workaround was to declare jest.mock in another file and then import it in the test.

gabberr avatar Oct 18 '21 13:10 gabberr

Our workaround was to declare jest.mock in another file and then import it in the test.

@gabberr, could you provide an example? I've tried it, but I still get the same error.

diego-aquino avatar Nov 11 '21 14:11 diego-aquino

Hope this issue will be resolved soon. I try to switch from babel-jest to @swc/jest and this is the only remaining issue has left that blocks me from actually switch.

nvh95 avatar Nov 16 '21 07:11 nvh95

@diego-aquino here:

Create a file 'src/mocks/bunny.ts':

const mockedBunny = jest.fn()
jest.mock(
  'actual/bunny/file',
  () => mockedBunny
)

export default mockedBunny

Inside the test where you want to mock Bunny:

import 'src/mocks/bunny'

//  OR, if you want to set mock implementation in the test

import bunnyMock from 'mocks/bunny'

bunnyMock.mockImplementation(() => 'my mocked bunny')


gabberr avatar Nov 16 '21 11:11 gabberr

Try with

{
    "jsc": {
        "transform": {
            "hidden": {
                "jest": true
            }
        }
    }
}

I just did and it seems to be working

See https://github.com/swc-project/swc/blob/2462b9941f94bc475cf9ff9c67e3b7c1f98739cc/node-swc/tests/transform/hidden_jest.js

Ayc0 avatar Nov 24 '21 01:11 Ayc0

Update: setting hidden.jest = true is already set by @swc/jest, but it wasn't applied, #44 fixes that.

At the moment of my message, the latest version of @swc/jest (0.2.9) doesn't include the fix yet, but I think it'll be released in the close future

Ayc0 avatar Nov 24 '21 12:11 Ayc0

im actually still running into this, any work around?

th3fallen avatar Dec 11 '21 15:12 th3fallen

@th3fallen have you tried https://github.com/swc-project/jest/issues/14#issuecomment-970189585 ?

@kdy1 The mentioned fix that closes this ticket was actually reverted, should this be reopened?

gabberr avatar Dec 15 '21 07:12 gabberr

@gabberr it was reverted indeed in swc-jest, but a commit was added to swc itself to fix the issue: see https://github.com/swc-project/jest/pull/44#issuecomment-980601069

Can you try with an up to date swc?

Ayc0 avatar Dec 15 '21 07:12 Ayc0

Ah, I forgot it. @Ayc0 Thank you!

kdy1 avatar Dec 15 '21 07:12 kdy1

There should be a test for jest's mocking mechanism: https://github.com/swc-project/jest/pull/46 So it should work now.

Can you try updating your versions of both swc and swc-jest to see if it is still broken for you? (And also can you send a way to replicate the bug? So that we can add more tests)

Ayc0 avatar Dec 15 '21 07:12 Ayc0

There should be a test for jest's mocking mechanism: #46 So it should work now.

Can you try updating your versions of both swc and swc-jest to see if it is still broken for you? (And also can you send a way to replicate the bug? So that we can add more tests)

It still doesn't work if you want to mock implementation and pass mock function as the desired export for the module that you're trying to mock. See: https://github.com/MhMadHamster/swc-jest-mock-bug/tree/master You can get around it tho by doing something like this:

import { callFnOne } from "./index";

const mockedImpl = jest.fn();

jest.mock("./to-be-mocked", () => ({
  fnOne: (...args) => mockedImpl(...args),
}));

describe("", () => {
  it("fnOne test", () => {
    callFnOne()
    expect(mockedImpl).toBeCalledTimes(1);
  });
});

MhMadHamster avatar Dec 15 '21 18:12 MhMadHamster

I forked your repo here: https://github.com/Ayc0/swc-jest-mock-bug if you want to give it a try.

I think this is related to: https://jestjs.io/docs/es6-class-mocks#calling-jestmock-with-the-module-factory-parameter

image

In the fork, you can see that I disabled swc and here are my results without swc: image

and here with swc: image

There seems to be a difference with the hoisting of mock* variables, but your example still failed without SWC.

The mock* could be investigated indeed (what do you think @kdy1?)

Ayc0 avatar Dec 16 '21 00:12 Ayc0

I think the exception with swc should match the exception without swc. Seems like a different issue though.

kdy1 avatar Dec 16 '21 06:12 kdy1

I agree, I'll open another issue

Ayc0 avatar Dec 16 '21 06:12 Ayc0

I opened https://github.com/swc-project/jest/issues/59 for this issue specifically.

I think we can close this one then

Ayc0 avatar Dec 16 '21 11:12 Ayc0

in my case the mocking failure is from this...

import { getUserId } from 'shared/auth';

getUserId.mockReturnValue('1');

describe("", () => {
  it("getUserId test", () => {
    
    expect(getUserId).toBe(1);
  });
});

th3fallen avatar Dec 16 '21 14:12 th3fallen

I think this is related to: https://jestjs.io/docs/es6-class-mocks#calling-jestmock-with-the-module-factory-parameter

I discovered that i had this issue because I was using ts-jest before, and apparently it allows using local variables in the mock factory, hence i thought issue was in swc 😕

MhMadHamster avatar Dec 17 '21 17:12 MhMadHamster

I think ts-jest is using tsc which usually changes the variables from const/let to var (and var variables are hoisted to the top of the file).

But this is a guess.

Ayc0 avatar Dec 17 '21 17:12 Ayc0

Is this still an issue?

kdy1 avatar Jan 27 '22 12:01 kdy1

yes

th3fallen avatar Jan 28 '22 16:01 th3fallen

Just installed latest @swc/core and @swc/jest and encountered the same issue.

const replaceMock = jest.fn(() => ({ type: '' }));
jest.mock('connected-react-router', () => ({
  replace: replaceMock,
}));
Screen Shot 2022-02-03 at 2 33 55 AM

kylemh avatar Feb 02 '22 19:02 kylemh

@kylemh as mentioned above, I don't think that this code would work either with just jest (and babel)

jest.mock isn't meant to be used with code defined out of its scope (see https://jestjs.io/docs/es6-class-mocks#calling-jestmock-with-the-module-factory-parameter)

instead you should do:

jest.mock('connected-react-router', () => {
  const replaceMock = jest.fn(() => ({ type: '' }));
  return {
    replace: replaceMock,
  };
});

Ayc0 avatar Feb 03 '22 18:02 Ayc0

so you're suggesting that ts-jest is making this work?

kylemh avatar Feb 03 '22 18:02 kylemh

Maybe, I think it's related to https://github.com/swc-project/jest/issues/14#issuecomment-996890800.

But according to jest's doc, your code isn't supposed to work.

Ayc0 avatar Feb 03 '22 18:02 Ayc0

Btw, when I inject your code in babel repl with the plugin jest-hoist, it throws this error:

image

But it doesn't throw with the following code (because variables starting in mock are allowed in jest.mock):

const mockReplace = jest.fn(() => ({ type: '' }));
jest.mock('connected-react-router', () => ({
  replace: mockReplace,
}));

Ayc0 avatar Feb 03 '22 18:02 Ayc0

Sorry. To be clear, what I shared was just a snippet of the test code and I didn't share any source code.

I'm calling jest.mock() at the top-level scope of the test file and the test file is importing and testing a component that leverages connected-react-router.

kylemh avatar Feb 03 '22 21:02 kylemh

omg I was scratching my head the whole day. Lucky I saw this issue!

robertwt7 avatar Mar 22 '22 11:03 robertwt7