I have the following server class :
import express, { Request, Response } from 'express'; export default class Server { server: any; exp: any; constructor() { this.exp = express(); this.exp.get('/', (_req: Request, res: Response) => { res.json('works'); }); } start(): void { this.server = this.exp.listen(3000); } stop(): void { this.server.close(); } }
I’m using supertest for end-to-end testing. I wish to start my application beforeAll tests and stop it when the tests are done.
It’s easy to do that using beforAll and afterAll where I can just once instanciate the Server class and call the start and close methods.
But as I have 10+ controllers to test, I want to avoid to start and stop the server during each test file.
I found on the documentation the setupFiles and setupFilesAfterEnv but I can’t stop the server since the instance is not “shared” in the two files.
This is an example of 1 test file :
import supertest from 'supertest'; describe('Album Test', () => { let app: App; beforeAll(async (done) => { app = new App(); await app.setUp(); // database connection (not mentionned in the preivous example) done(); }); afterAll(async (done) => { await app.close(); app.server.stop(); done(); }); const api = supertest('http://localhost:3000'); it('Hello API Request', async () => { const result = await api.get('/v1/user'); expect(result.status).toEqual(200); ... }); });
This works totally fine but I’m duplicating this beforeAll and afterAll methods in every test file. Is there a way to declare it only once ?
Thanks
Advertisement
Answer
You could use setupFiles to set up test fixtures globally. You can assign variables that you want to use in multiple test files to Node.js global object.
E.g.
app.ts
:
import express, { Request, Response } from 'express'; export default class Server { server: any; exp: any; constructor() { this.exp = express(); this.exp.get('/', (_req: Request, res: Response) => { res.json('works'); }); } start(): void { this.server = this.exp.listen(3000); } stop(): void { this.server.close(); } }
app.setup.js
:
const App = require('./app').default; beforeAll(() => { global.app = new App(); global.app.exp.set('test setup', 1); console.log('app setup'); }); afterAll(() => { console.log('app stop'); });
jest.config.js
:
module.exports = { preset: 'ts-jest/presets/js-with-ts', testEnvironment: 'node', setupFilesAfterEnv: [ './jest.setup.js', '/Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/61659975/app.setup.js', ], testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], verbose: true, };
a.controller.test.js
:
describe('controller a', () => { it('should pass', () => { console.log('test setup:', global.app.exp.get('test setup')); expect(1 + 1).toBe(2); }); });
b.controller.test.js
:
describe('controller b', () => { it('should pass', () => { console.log('test setup:', global.app.exp.get('test setup')); expect(1 + 1).toBe(2); }); });
unit test results:
PASS stackoverflow/61659975/a.controller.test.js controller a ✓ should pass (5ms) console.log app setup at Object.<anonymous> (stackoverflow/61659975/app.setup.js:6:11) console.log app setup at Object.<anonymous> (stackoverflow/61659975/app.setup.js:6:11) console.log test setup: 1 at Object.<anonymous> (stackoverflow/61659975/b.controller.test.js:3:13) console.log test setup: 1 at Object.<anonymous> (stackoverflow/61659975/a.controller.test.js:3:13) console.log app stop at Object.<anonymous> (stackoverflow/61659975/app.setup.js:10:11) console.log app stop at Object.<anonymous> (stackoverflow/61659975/app.setup.js:10:11) PASS stackoverflow/61659975/b.controller.test.js controller b ✓ should pass (3ms) Test Suites: 2 passed, 2 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 6.749s, estimated 12s