Home > Blockchain >  TypeError: _app.app.close is not a function using jest 27.5.1
TypeError: _app.app.close is not a function using jest 27.5.1

Time:02-15

I have a test which is failing on Jest 27.5.1 (with babel-jest at the same version) with this error

enter image description here

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              
-----------|---------|----------|---------|---------|-------------------
  • Related