Sunday, May 12, 2024
 Popular · Latest · Hot · Upcoming
103
rated 0 times [  105] [ 2]  / answers: 1 / hits: 6003  / 4 Years ago, tue, september 1, 2020, 12:00:00

I'll start with an example of how I set up my tests for a backend server. TL;DR at bottom.


This file represents my server:


//server.js
const express = require('express');

class BackendServer {
constructor(backingFileDestination, database) {
this.server = express();
/* Set up server ... */
/* Set up a mysql connection ... */
}

closeMySQLConnectionPool = () => {
/* Close the mysql connection ... */
};
}

module.exports = BackendServer;

In my package.json, I have the following:


"jest": {
"testEnvironment": "node",
"setupFilesAfterEnv": [
"<rootDir>/tests/setupTests.js"
]
}

Which allows me to use this setup file for my tests:


//setupTests.js
const { endpointNames } = require('../../src/common/endpointNames.js');
const BackendServer = require('../server.js');
const server = new BackendServer(
'../backing_files_test/',
'test',
);
const supertester = require('supertest')(server.server);

// drop, recreate, and populate the database once before any tests run
beforeAll(async () => {
await supertester.post(endpointNames.DROP_ALL_TABLES);
await supertester.post(endpointNames.CREATE_ALL_TABLES);
await supertester.post(endpointNames.POPULATE_ALL_TABLES);
});

// clean up the local setupTests server instance after all the tests are done
afterAll(async () => {
await server.closeMySQLConnectionPool();
});

Notice how I had to import the BackendServer class and instantiate it, then use that instance of it.


Now, I have other test files, for example test1.test.js:


//test1.test.js
const { endpointNames } = require('../../src/common/endpointNames.js');
const BackendServer = require('../server.js');
const server = new BackendServer(
'../backing_files_test/',
'test',
);
const supertester = require('supertest')(server.server);

// clean up the local server instance after all tests are done
afterAll(async () => {
await server.closeMySQLConnectionPool();
});

test('blah blah', () => {
/* Some test ... */
});

The problem is when I go to write test2.test.js, it will be the same as test1.test.js. This is the issue. For every test file, I need to instantiate a new server and then have a separate afterAll() call that cleans up that server's SQL connection. I can't stick that afterAll() inside of setupTests.js because it needs to operate on test1.test.js's local server instance.


TL;DR: Each of my test files instantiates a new instance of my server. What I want is to instantiate the server once in setupTests.js and then simply use that instance in all my tests. Is there a good way to share this single instance between all my test files?


More From » jestjs

 Answers
17

I was able to figure out a way to achieve what I wanted. It involves instantiating variables in setupTests.js and then exporting getters for them.


//setupTests.js
const { endpointNames } = require('../../src/common/endpointNames.js');
const BackendServer = require('../server.js');
const server = new BackendServer(
'../backing_files_test/',
'test',
);
const supertester = require('supertest')(server.server);

// drop, recreate, and populate the database once before any tests run
beforeAll(async () => {
await supertester.post(endpointNames.DROP_ALL_TABLES);
await supertester.post(endpointNames.CREATE_ALL_TABLES);
await supertester.post(endpointNames.POPULATE_ALL_TABLES);
});

// clean up the local setupTests server instance after all the tests are done
afterAll(async () => {
await server.closeMySQLConnectionPool();
});

const getServer = () => { // <==== ADD THESE 2 FUNCTIONS
return server;
};

const getSupertester = () => { // <==== ADD THESE 2 FUNCTIONS
return supertester;
};

module.exports = { getServer, getSupertester }; // <==== EXPORT THEM

I added a couple functions to the end of setupTests.js that, when called, will return whatever the local variables point to at the time. In this case, server and supertester are declared with const, so I could have exported them directly I think, but in other cases I had some variables that I wanted to share that were declared with let, so I left it this way.


Now I have functions exported from setupTests.js that I can import in my test files like this:


//test1.test.js
const { endpointNames } = require('../../src/common/endpointNames.js');
const { getServer, getSupertester } = require('./setupTests.js');

test('blah blah', () => {
/* Some test using getSupertester().post() or getServer().someFunction() ... */
});

So now I can have local variables inside setupTests.js that are accessible in my .test.js files.


This makes my whole testing process cleaner because I only need to set up and tear down one server, which means only 1 connection pool for my SQL server and less code duplication of having to instantiate and clean up a new server in every .test.js file.


Cheers.


[#2762] Friday, August 28, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
emiliano

Total Points: 381
Total Questions: 109
Total Answers: 93

Location: Jersey
Member since Fri, Oct 1, 2021
3 Years ago
emiliano questions
;