Unmock function after mockimplementation - node.js

I'm having a bit of trouble unmocking a function.
I first mock it and now I can't unmock it
//myClass.js
class myClass {
static check(v1,v2) {
return v1 > v2;
}
static async getinfo(v1,v2) {
if (this.check(v1,v2)) {
return await get('api.google.com');
}
return [];
}
}
//myclass.spec.js
describe('Testing myClass', () => {
describe('testing processing', () => {
it('should return result', () => {
const mockPatch = jest.fn().mockImplementation((version, solution) => false);
myClass.check = mockCheck;
try {
const result = await myClass.getinfo(1,2);
expect(result).toBe.([]);
}catch(e) {
throw e;
}
})
})
describe('Testing check', () => {
it('should return true', () => {
expect(myClass.check(2,1)).toBe.true
})
})
})
I already try with
myClass.check.mockRestore()
beforeEach(() => {myClass.check.mockRestore()})
jest.unmock('./myClass.js)
Is there anyway I can solve this? I read all the jest doc and i couldn't find anything

Methods should never be mocked by reassigning them, there is no way how Jest could restore their original implementation this way.
This should always be done with spyOn:
jest.spyOn(myClass, 'check').mockReturnValue(false)
This way a method can be restored with restoreMock or restoreAllMocks. This should be preferably enabled globally in Jest configuration.

I'm assuming that what you're hoping to do is to mock an implementation for use in a specific test, but then have your other tests function without the mocking.
If so, I think you could use the module mocking strategy in conjunction with mockReturnValueOnce.
Be sure to import your module at the top of your tests, then to call jest.mock with the same path. After that, you should be able to call myClass.check.mockReturnValueOnce, and it will be mocked until the next time it is called. After that, it will function normally 👍

Related

How to mock a function from the same module as the function being tested

So, I have two methods on a Node project:
export function methodA() {
const response = await methodB();
return response.length ? 'something' : 'else';
}
export function methodB() {
const array = await getData(); // Access database and make API calls
return array[];
}
methodA calls methodB and methodB makes stuff that I don't care right now for my unit testing purposes, so I want to mock methodB so it will return an empty array and won't try to make any database or API calls. The issue is that I can't actually mock methodB, as my test is still calling the actual function.
Here's my test:
describe('method testing', () => {
it('calls method', async () => {
const response = await myModule.methodA();
expect(response).toBe('else');
});
});
That test is failing, because jest is still calling the actual methodB which is meant to fail, as it can't connect to the database or reach APIs, so, this is what I tried doing to mock methodB:
Spying on the method:
import * as myModule from '#/domains/methods';
jest.spyOn(myModule, 'methodB').mockImplementation(() => [] as any);
// describe('method testing', () => {...
Mocking the entire file except for the methodA:
jest.mock('#/domains/methods', () => {
const originalModule = jest.requireActual('#/domains/methods')
return {
...originalModule,
methodB: jest.fn().mockReturnValue([])
}
});
// describe('method testing', () => {...
I have also tried:
Mocking methodB inside each test and inside describe
Spying methodB inside each test and inside describe
Some variations of those examples I wrote above
I'm not entirely sure on what to do right now, so any light would be appreciated.
#Update: Altough the problem is similar, this is not a duplicate question and this (How to mock functions in the same module using Jest?) does not answer my question.

Function is a mock in Jest, but not really mocking

I mocking a function, and for some reason, the code is still running the original function,
I made sure that the function is indeed mocked using isMockFunction,
import { getTables, getExportFiles } from 'rds-formatter';
jest.mock('rds-formatter', () => {
return {
...jest.requireActual('rds-formatter'),
getExportFiles: jest.fn(() => Promise.resolve('return something')),
});
Now the thing is Im testing an asyncGenerator function
export async function *getTables(assetId: string, payload: Record<string, unknown>) {
const { parquetFiles, tablesInfoFile } = await getExportFiles(s3Client, payload);
return parquetFiles }
My test looks like this:
it('', async () => {
console.log(jest.isMockFunction(getExportFiles)); //returns true
const data = getTables('gfsdg', payload)
expect((await data.next()).value).toBe('')
});
The error I'm getting is s3Client.listObjectsV2 is not a function This error is from inside the function I'm trying to mock, I know this happens because I'm not passing a real client, but from my understanding the compiler shouldn't even go inside the mocked function, no?

How to change jest.mock value for different tests when mocked class is a dependency on on the SUT?

I am testing a class DogService.ts. But DogService has a private dependency called CatService that gets new'ed up in the constructor. I can successfully mock the dependency using:
jest.mock('../CatService', () => {
return {
CatService: jest.fn().mockImplementation(() => {
return {
someFunction: (async (someArg) => {
return await someAsyncMethod();
})
}
})
}
});
And it gets injected fine in the test:
describe("", () => {
it("", async () => {
const dogService = new DogService();
...
});
});
There's no import for the CatService in my jest test file. The mock I guess is the import. However, I want to swap out the implementation of CatService in different tests. I have tried jest.resetModules() and a bunch of other things. Further, the above only seems to work when the mock is outside any tests. If I move it into the describe() function the real CatService is used.
Any ideas how to do this? Most tutorials are for mocking classes or functions you directly use in the jest test, but obviously I am mocking a dependency.

How to use jest.each asynchronously

I am having problems loading filenames into jest.each asynchronously.
My code:
let files: string[][]
function getFilesWorking() {
files = [["test1"], ["test2"]]
}
async function getFilesAsync() {
files = await Promise.resolve([["test1"], ["test2"]])
}
beforeAll(() => {
console.log("before")
})
describe.only("Name of the group", () => {
getFilesAsync()
test.each(files)("runs", f => {})
})
beforeAll is executed before each test but NOT before initialization of test.each, so I end up with undefined.
How can I load files before using test.each?
You can pass an async callback to beforeAll and await getFilesAsync within it
beforeAll(async () => {
await getFilesAsync();
})
As of Jest 28.1.3 and prior, this is not possible. There is an open issue documenting this behavior.
The best thing you can do for now is put your tests in a regular it() test and do a deep value comparison:
it('tests an array of cases', async () => {
const data = await getSomeAsyncData()
const expectedData = [ ... ]
expect(data).toEqual(expectedData)
})
You can use beforeEach to set up code that will run prior to tests for any given scope, https://jestjs.io/docs/setup-teardown:
beforeEach(() => {
console.log('before every test');
});
describe.only(('Name of the group') => {
beforeEach(() => {
console.log('before tests in this describe block');
})
})
Jest is only going to run the tests in your describe.only block. If you want to use beforeEach in other blocks and run those tests as well, change describe.only to describe.
(Edit: I know this is a year late, I'm just trying to look for a similar problem/solution set and thought I could answer this.)

Accessing .mock property of an automocked function

I have this code:
import * as a from 'a-a';
jest.mock('a-a');
describe('a-a', () => {
beforeAll(async () => {
const x = await a.x(1); // Calls the mock
console.log(x); // 1
console.log(a.x.mock) // Undefined
});
});
The mock function is:
export async function x(data) {
cache.push(data);
console.log('HERE'); // this is printed
return data;
}
The mock of the module is in the __mocks__ directory.
The a.x() calls the mocked function, but a.x.mock is undefined.
How is that possible? Where is the .mock property?
So, after some investigation I found out that the functions declared in the __mocks__ directory aren't wrapped by jest.fn() by default.
Personally I find the thing a bit confusing.
So you can do both
function x(data) {
cache.push(data);
return cache;
}
jest.mock('a-a', () => ({x: x}))
if you do everything in the same file, or
jest.mock('a-a');
and then in the __mocks__/a-a.js file
export const x = jest.fn(async (data) => {
cache.push(data);
return cache;
});

Resources