Jest v27 FSREQCALLBACK warning with FeathersJS NeDB services - jestjs

Since an upgrade to Jest v27 on my FeathersJS app, a bunch of warnings occurs at the end of the test suites:
Jest has detected the following 24 open handles potentially keeping Jest from exiting:
● FSREQCALLBACK
5 | export default (app: Application): NeDB<any> => {
6 | const dbPath = app.get('nedb');
> 7 | const Model = new NeDB({
| ^
8 | filename: path.join(dbPath, 'billing-departments.db'),
9 | autoload: true,
10 | });
at Object.<anonymous>.async.setImmediate (node_modules/async/lib/async.js:96:15)
at node_modules/async/lib/async.js:696:21
at Array.forEach (<anonymous>)
at _each (node_modules/async/lib/async.js:32:24)
at _insert (node_modules/async/lib/async.js:681:11)
at Object.push (node_modules/async/lib/async.js:708:15)
at Executor.Object.<anonymous>.Executor.push (node_modules/nedb/lib/executor.js:57:16)
at Datastore.Object.<anonymous>.Datastore.loadDatabase (node_modules/nedb/lib/datastore.js:88:17)
at new Datastore (node_modules/nedb/lib/datastore.js:76:29)
at Object.<anonymous>.exports.default (src/models/billing-departments.model.ts:7:17)
at Function.Object.<anonymous>.exports.default (src/services/billing-departments/billing-departments.service.ts:8:12)
at Function.configure (node_modules/#feathersjs/feathers/lib/application.js:59:8)
at Function.Object.<anonymous>.exports.default (src/services/index.ts:28:7)
at Function.configure (node_modules/#feathersjs/feathers/lib/application.js:59:8)
at Object.<anonymous> (src/app.ts:50:4)
at Object.<anonymous> (test/services/sms.test.ts:1:1)
...
This warning is reported for each of my service test even freshly created by the cli.
It occurs with this kind of simple test:
import app from '../../src/app';
describe('\'auth-sms\' service', () => {
it('registered the service', () => {
const service = app.service('auth-sms');
expect(service).toBeTruthy();
});
});
How to solve this open handles problem properly?

Related

Mongoose: looks like you're trying to test a Mongoose app with Jest's default jsdom test environment

Can anyone help here. I couldn't run my test file. Below is the error & test file.
jest.useFakeTimers();
import { orderController } from '../controllers/orderController';
import { orderService } from '../service/orderService';
const res: any = {
send(object: any) {
return object;
}
};
describe("Methods in orderController", () => {
test("checking an API", async () => {
const patientDetailsMock = await jest.spyOn(orderService, 'getPatientDetails');
//const req = {}
//await orderController.createOrder(req, res);
expect(patientDetailsMock).toHaveBeenCalled();
//console.log("hello..inside test",patientDetailsMock)
//expect(patientDetailsMock).toBeTruthy();
});
});
>chandanasriharimummaneni#PTRL671:~/Desktop/demo/JestTesting/node-orders$ npm test
> node-orders#0.0.1 test /home/chandanasriharimummaneni/Desktop/demo/JestTesting/node-orders
> jest
FAIL src/test/orderController.test.ts
Methods in orderController
✕ checking an API (3ms)
● Methods in orderController › checking an API
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
21 | //const req = {}
22 | //await orderController.createOrder(req, res);
> 23 | expect(patientDetailsMock).toHaveBeenCalled();
| ^
24 | //console.log("hello..inside test",patientDetailsMock)
25 | //expect(patientDetailsMock).toBeTruthy();
26 |
at Object.<anonymous> (src/test/orderController.test.ts:23:36)
console.warn node_modules/mongoose/lib/helpers/printJestWarning.js:4
Mongoose: looks like you're trying to test a Mongoose app with Jest's default jsdom test environment. Please make sure you read Mongoose's docs on configuring Jest to test Node.js apps: http://mongoosejs.com/docs/jest.html
console.info node_modules/common-component/lpl/utils/logger/logger.js:184
{ uniqId: '', req: '', jsonObject: '', description: '', arguments: '' } [
'AWS-MIS-Config',
'{"provider":"amazon","keyId":"AKIAT5D3HEZTLAOGKVPG","key":"ZrPLIGmGXWh/nPh0euj+042m+yUUJUzUYvwPMoRR","region":"us-east-1"}'
]
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.994s, estimated 2s
Ran all test suites.
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
What are ways to mock db and methods using mongoose ORM?
Is there any way to mock db connection with object reference ? Also help me to to clear the issue. I have changed jsdom test environment.

why can't you mock a re-exported primitive value?

I'm trying to change the value of a primitive config object during tests. One of my files under test re-exports a primitive that is conditional on the config values.
I'm finding that when the value is wrapped in a function, then mocking it and asserting on it works perfectly.
However when the value is re-exported as a primitive, the value is not mocked, and is undefined.
Simplified example:
config.ts
export const config = {
environment: 'test'
};
app.ts
import { config } from './config';
export const app = () => config.environment;
export const environment = config.environment;
app.spec.ts
import { app, environment } from './app';
import * as config from './config';
jest.mock('./config', () => ({
config: {},
}));
beforeEach(() => {
jest.resetAllMocks();
});
const mockConfig = config.config as jest.Mocked<typeof config.config>;
test('app', () => {
mockConfig.environment = 'prod';
expect(app()).toEqual('prod');
});
test('environment', () => {
mockConfig.environment = 'nonprod';
expect(environment).toEqual('nonprod');
});
The first test passes, but the second test "environment" fails. Why?
✕ environment (3 ms)
● environment
expect(received).toEqual(expected) // deep equality
Expected: "nonprod"
Received: undefined
19 | test('environment', () => {
20 | mockConfig.environment = 'nonprod';
> 21 | expect(environment).toEqual('nonprod');
| ^
22 | });
23 |
at Object.<anonymous> (config/app.spec.ts:21:29)
The problem could be related with the order files are read. The app file is the first one to be read, and then the config file is read because its imported on the app one. But, probably the app code run first, so the variable was set as undefined (because the config one had not a value at the time).
The same does not happen with the app function, because it reads the config variable only after the function is called. And at that time, the variable already was set.

How to mock x-date-pickers from mui in jest?

I added a DateTimePicker to my app which seems to work, however, I'm unable to mock the picker in my Jest tests.
I keep getting the following error:
Test suite failed to run
TypeError: (0 , _material.generateUtilityClasses) is not a function
7 | import type { Property, EnumProperty } from "../../types";
> 8 | import { DateTimePicker } from "#mui/x-date-pickers/DateTimePicker";
| ^
9 | import { DateTime } from "luxon";
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/internals/components/PickersToolbarText.js:32:54)
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/DateTimePicker/DateTimePickerToolbar.js:20:27)
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/DesktopDateTimePicker/DesktopDateTimePicker.js:20:30)
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/DesktopDateTimePicker/index.js:13:30)
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/DateTimePicker/DateTimePicker.js:22:30)
at Object.<anonymous> (node_modules/#mui/x-date-pickers/node/DateTimePicker/index.js:13:23)
at Object.<anonymous> (src/components/myFile/myFile.tsx:8:1)
I've tried each of the following, but can't get jest to detect the mock.
jest.mock("#mui/x-date-pickers", () => require("../../../__mocks__/x-date-pickers"));
jest.mock("#mui/x-date-pickers", () => (
<div>
Hello
</div>
));
jest.mock("#mui/x-date-pickers");
Below is the line throwing the error. It's just a regular import statement:
import { DateTimePicker } from "#mui/x-date-pickers/DateTimePicker";
My mocked file at the location "../../../mocks/x-date-pickers" relative to the unit test file. I'm not expecting the mock to work yet, but I'm at least expecting it to be picked up.
import React from "react";
import { DateTimePickerProps } from "#mui/x-date-pickers";
export const DateTimePicker = (props: DateTimePickerProps) => (
<input
data-testid="mockedDateField"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
props.onChange(event.target.value);
}}
/>
);
Any help would be appreciated!
The problem was I needed to add DateTimePicker to the end of my mock:
jest.mock("#mui/x-date-pickers/DateTimePicker", () => require("../../../__mocks__/x-date-pickers"));

How to suppress Jest Linter errors from import files?

So I'm trying to do some basic API testing with Jest by importing a function from handler.ts but Jest crawls through the handler ts imports and gives me linter errors for a file that handler importest from my libs folder when all I want to do is check if the result of that function equals what I want it to equal.
Here's my test file test/handler.test.ts:
import { getInbox } from './../handler'
import * as myMongo from '../../../libs/mongo';
import { Db } from 'mongodb';
const productionDbPromise: Promise<Db> = myMongo.getProductionDb();
test("Case page 1, limit 5", async ()=>{
const page = 1;
const limit = 5;
const event = {
queryStringParameters: {
page: page,
limit: limit
}
};
const productionDb = await productionDbPromise;
const seekerCollection = productionDb.collection('seekers');
const totalDocs = await seekerCollection.countDocuments({ lastMessageDate: { $ne: null } });
const code = 200;
const status = 'OK';
const res: any = await getInbox(event);
expect(res.code).toEqual(code);
expect(res.status).toEqual(status);
expect(res.json().totalDocs).toEqual(totalDocs);
expect(res.json().seekers.length).toEqual(limit);
});
And here's the error:
Test suite failed to run
TypeError: twilio is not a function
6 | export const client = twilio(accountSid, authToken);
7 | export const messagingServiceSid = process.env.TWILIO_SERVICE_ID;
> 8 |
| ^
at Object.<anonymous> (../../libs/twilio.ts:8:18)
at Object.<anonymous> (../../libs/message.ts:7:18)
at Object.<anonymous> (handler.ts:14:19)
at Object.<anonymous> (__test__/handler.test.ts:4:19)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 12.086 s
npm ERR! Test failed. See above for more details.
Any idea how to get it to ignore this? (which by the way the function I'm testing does not even use any exports from that libs file, and the twilio object is correctly imported on the first line of that file)
It's not Jest's responsibility to run a linter, also it doesn't crawl through any modules that weren't explicitly imported.
This is not linter but runtime error, and it cannot be suppressed or discarded. The problem is exactly what it says:
TypeError: twilio is not a function
Call stack gives a good idea where it comes from:
at Object.<anonymous> (../../libs/twilio.ts:8:18)
at Object.<anonymous> (../../libs/message.ts:7:18)
at Object.<anonymous> (handler.ts:14:19)
at Object.<anonymous> (__test__/handler.test.ts:4:19)
handler.ts depends on message.ts, and message.ts depends on twilio.ts, where the error happens. If twilio is not supposed to be available in tests, either it or one of these modules need to be mocked.

Jest automatic-mocks: funny example outcome

this refers to the facebook example tutorials
// utils.js
// Copyright 2004-present Facebook. All Rights Reserved.
export default {
authorize: () => 'token',
isAuthorized: (secret) => secret === 'wizard',
};
below is the test file. Instead of adding auto mock at the config file, I added inside the code to show the differences.
import utils from './utils';
jest.enableAutomock();
test('implementation created by automock', () => {
expect(utils.authorize('wizzard')).toBeUndefined();
expect(utils.isAuthorized()).toBeUndefined();
});
outcome:
TypeError: Cannot read property 'default' of undefined
6 |
7 | test('implementation created by automock', () => {
> 8 | expect(utils.authorize('wizzard')).toBeUndefined();
| ^
9 | expect(utils.isAuthorized()).toBeUndefined();
10 | });
11 |
at Object.utils (__tests__/example/automatic-mocks/genMockFromModule.test.js:8:10)
Why is that? it happens to another file automock.test.js. The error message is the same.
// Copyright 2004-present Facebook. All Rights Reserved.
import utils from './utils';
jest.enableAutomock();
test('if utils are mocked', () => {
expect(utils.authorize.mock).toBeTruthy();
expect(utils.isAuthorized.mock).toBeTruthy();
});
test('mocked implementation', () => {
utils.authorize.mockReturnValue('mocked_token');
utils.isAuthorized.mockReturnValue(true);
expect(utils.authorize()).toBe('mocked_token');
expect(utils.isAuthorized('not_wizard')).toBeTruthy();
});
Below example works for me, I use jestjs with typescript and ts-jest.
the docs say:
Note: this method was previously called autoMockOn. When using babel-jest, calls to enableAutomock will automatically be hoisted to the top of the code block. Use autoMockOn if you want to explicitly avoid this behavior.
utils.ts:
const utils = {
getJSON: data => JSON.stringify(data),
authorize: () => 'token',
isAuthorized: secret => secret === 'wizard'
};
export default utils;
utils.spec.ts:
jest.enableAutomock();
import utils from './utils';
describe('automatic mocks test suites', () => {
it('should mock all methods of utils', () => {
expect((utils.getJSON as jest.Mock).mock).toBeTruthy();
expect(jest.isMockFunction(utils.authorize)).toBeTruthy();
expect(jest.isMockFunction(utils.isAuthorized)).toBeTruthy();
});
test('implementation created by automock', () => {
expect(utils.authorize()).toBeUndefined();
expect(utils.isAuthorized('wizard')).toBeUndefined();
});
it('mocked implementation', () => {
(utils.getJSON as jest.Mock).mockReturnValue(123);
expect(utils.getJSON({ name: 'test' })).toBe(123);
});
});
Unit test result:
PASS src/automatic-mocks/utils.spec.ts (17.906s)
automatic mocks test suites
✓ should mock all methods of utils (4ms)
✓ implementation created by automock (2ms)
✓ mocked implementation (1ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 22.923s, estimated 23s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/automatic-mocks

Resources