I have a test which is failing on Jest 27.5.1 (with babel-jest at the same version) with this error
I dont get this error when using Jest 26.6.3 (with babel-jest also at 26.6.3) My test file
import supertest from 'supertest';
import {
buildAccount,
buildAuthenticationType,
createAccount,
createAuthenticationType,
} from './factories';
import {
startDatabase,
ENDPOINT_PREFIX,
clearDatabase,
doLogin,
} from './utils';
import { Account, AuthenticationType } from 'data/models';
import { app } from 'server/app';
const agent = supertest.agent(app);
const ENDPOINT = `${ENDPOINT_PREFIX}/account`;
describe('Account tests', () => {
beforeEach(async () => {
await startDatabase();
await doLogin(agent);
});
afterAll(async () => {
await clearDatabase();
console.log(typeof app.close, app.close);
await app.close();
});
test('/POST - Response with a new created account', async () => {
const relAuthenticationTypeIdDict = await buildAuthenticationType({});
const relFakeAuthenticationTypeId = await createAuthenticationType(
relAuthenticationTypeIdDict
);
const fakeAccount = await buildAccount({
authenticationTypeId: relFakeAuthenticationTypeId.authenticationTypeId,
});
const response = await agent.post(ENDPOINT).send(fakeAccount);
expect(response.status).toBe(201);
expect(response.statusCode).toBe(201);
const responseAccount = response.body.data;
const account = await Account.findByPk(responseAccount.accountId);
expect(account.email).toBe(fakeAccount.email);
expect(account.emailVerified).toBe(fakeAccount.emailVerified);
expect(account.isPrimary).toBe(fakeAccount.isPrimary);
expect(account.username).toBe(fakeAccount.username);
expect(account.password).toBe(undefined);
expect(account.pictureUrl).toBe(fakeAccount.pictureUrl);
expect(account.socialAccountId).toBe(fakeAccount.socialAccountId);
expect(account.authenticationTypeId).toBe(fakeAccount.authenticationTypeId);
});
});
My app.js file
import express from 'express';
import path from 'path';
import logger from 'morgan';
import passport from 'passport';
import swaggerUi from 'swagger-ui-express';
import { adminbroRouter } from './routes/adminbro.route';
import { router } from './routes';
import { sessionParser } from './session';
import { swaggerDocument } from './swagger';
import {
errorHandler,
responseHandler,
pageNotFoundHandler,
initResLocalsHandler,
} from './middlewares';
import { refreshFeedItemTagsQueue } from 'jobs/refresh-feed-item-tags';
import { ACCEPTED, NOT_FOUND, OK } from 'http-status';
import './passport';
const app = express();
// Swagger
app.use(
'/swagger',
swaggerUi.serveFiles(swaggerDocument),
swaggerUi.setup(swaggerDocument)
);
// Middlewares
app.use(logger('dev'));
app.use('/admin', adminbroRouter);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(sessionParser);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(initResLocalsHandler);
app.use(process.env.BASE_PATH, router);
// Use custom response handler
app.use(responseHandler);
// Use custom error handler
app.use(errorHandler);
// Page not found
app.use(pageNotFoundHandler);
export { app };
My server.js file
// eslint-disable-next-line import/first
import http from 'http';
import { app } from './app';
import { sessionParser } from './session';
import { websocketServer } from './ws';
import 'jobs/repeatable';
const server = http.createServer(app);
server.on('upgrade', (request, socket, head) => {
sessionParser(request, {}, () => {
websocketServer.handleUpgrade(request, socket, head, (ws) => {
websocketServer.emit('connection', ws, request);
});
});
});
/* istanbul ignore next */
const PORT = process.env.PORT || 8000;
/* istanbul ignore next */
server.listen(PORT, () => {
// eslint-disable-next-line no-console
console.log(`Express server listening on port ${PORT}`);
});
How is it possible that the older version of jest does not give this error while the newer one does?
CodePudding user response:
app
created by express()
doesn't have a close
method. But const server = http.createServer(app);
, the server
has a close
method.
You can start the server and listen to the connections in beforeAll
and call server.close
in afterAll
. To achieve this, you need to export server
so that the test file can get the server
.
The statement inside the if (require.main === module)
block will only be executed when running this script by node server.js
.
E.g.
app.ts
import express from 'express';
const app = express();
app.get('/heartbeat', (req, res) => {
res.sendStatus(200);
});
export { app };
server.ts
:
import http from 'http';
import { app } from './app';
const server = http.createServer(app);
const PORT = process.env.PORT || 8000;
if (require.main === module) {
server.listen(PORT, () => {
console.log(`Express server listening on port ${PORT}`);
});
}
export { server };
server.test.ts
:
import supertest from 'supertest';
import { app } from './app';
import { server } from './server';
const agent = supertest.agent(app);
describe('server', () => {
before((done) => {
server.listen(7890, () => {
console.log('Test server listening on port: 7890');
done();
});
});
after((done) => {
server.close(done);
});
it('should pass', () => {
return agent.get('/heartbeat').expect(200);
});
});
Test result:
server
Test server listening on port: 7890
✓ should pass
1 passing (20ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 84.62 | 75 | 50 | 84.62 |
app.ts | 100 | 100 | 100 | 100 |
server.ts | 75 | 75 | 0 | 75 | 9-10
-----------|---------|----------|---------|---------|-------------------