reusable const for various tests with mocha/chai - node.js

I'm running a serie of tests using mocha/chai.
I try to keep those tests as simple as possible so they are easy to read. That's why I'm using a lot of it() declarations.
For each one of those tests I'm using the same const.
Instead of re-declaring it each time I'd like to declare it just once and be done with it.
describe('#getLastAchievements', async function (): Promise<void> {
it("should return an array", async function (): Promise<void> {
const lastAch: any[] = await achievementsServiceFunctions.getLastAchievements(idAdmin, 3);
expect(lastAch).not.to.be.equal(null);
expect(lastAch).to.be.an('array');
});
it('should not be empty', async function (): Promise<void> {
const lastAch: Object[] = await achievementsServiceFunctions.getLastAchievements(idAdmin, 3);
expect(lastAch.length).to.be.above(0);
});
I tried declaring my const in various ways but everytime the tests don't run or the conts is undefined. Here is what I tried:
-declaring it before the it()
-declaring it in a before() function
-declaring it in a anonymous function then including the it() inside this function
-declaring it outside the describe() function
Is there a way to declare this const just once to re-use it for various tests?

You can declare stuff in beforeEach if they are the same for every it().
example:
describe('myTest', () => {
let foo;
beforeEach(() => {
foo = new Foo();
});
it('test 1', () => {
//do something with foo
});
it('test 2', () => {
//do something with foo
});
})

Related

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?

Unmock function after mockimplementation

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 👍

spyOn #react-native-firebase/analytics methods

Basically, I want to make sure the methods of analytics are called with certain properties but so far it is not working:
Cannot spy the logAppOpen property because it is not a function; undefined given instead
the library is successfully mocked since I can see console log out of my jest.fn():
jest.mock('#react-native-firebase/analytics', () => {
return () => ({
logAppOpen: jest.fn(() => console.log('mocked fun called')), //===>shown correctly
})
})
My class is:
import analytics from '#react-native-firebase/analytics';
export default class GA {
appStarted = async () =>{
console.log('appStarted called'); //==> showing
await analytics().logAppOpen();
}
}
my test:
it("should log app starting", async () =>{
const spy = jest.spyOn(analytics, 'logAppOpen') //===>FAILS HERE
congst ga = new GA();
await ga.appStarted();
expect(spy).toHaveBeenCalled();
})
but in my test: console.log(analytics) does show an empty object {}
It's analytics().logAppOpen() while jest.spyOn tries to spy on analytics.logAppOpen which doesn't exist.
For lazily evaluated spied functions it's easier to expose them as variables:
const mockLogAppOpen = jest.fn();
jest.mock('#react-native-firebase/analytics', () => {
return jest.fn()
.mockReturnValue({ logAppOpen: mockLogAppOpen });
});
This way it can be accessed for call assertions. There's no need for jest.spyOn for a function that is already a spy.

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.)

Spy on imported function

I want to spy on a function that is executed as soon as the file is required. In the example below I want to spy on bar. I have the following files.
code.ts
import {bar} from 'third-party-lib';
const foo = bar()
test.ts
import * as thirdParty from 'third-party-lib';
describe('test', () => {
let barStub: SinonStub;
beforeEach(() => {
barStub = sinon.stub(thridParty, 'bar')
})
it('should work', () => {
assert.isTrue(bar.calledOnce)
})
}
The stubing does not work. I think it is a timing issue. Bar gets stubed after it has been executed. The example above works if I wrap the first line in a function and execute that function in my test. But that is not what I want. Anybody an idea on how to stub such methods?
In this matter, we can use proxyquire to stub that third party lib as below:
import * as thirdParty from 'third-party-lib';
const proxyquire = require('proxyquire');
const barStub: SinonStub = sinon.stub();
proxyquire('./your-source-file', {
'third-party-lib': { bar: barStub }
});
describe('test', () => {
it('should work', () => {
assert.isTrue(barStub.calledOnce)
})
}
Ref:
https://www.npmjs.com/package/proxyquire
Hope it helps
I think your problem is you are never importing the file where you are doing const foo = bar(). You are just importing bar, thats all! Try importing or requiring your file inside the it block! That should trigger bar() and so, the test should pass!
it('should work', () => {
const foo = require(‘your_foo_file’)
assert.isTrue(bar.calledOnce)
})
Bye!

Resources