admin管理员组

文章数量:1295319

I need to close a PG-Promise database connection after testing a function in Jest.

This is initialised in one place(db.js) and required everywhere it is needed. In the case of the code below, it is required by seed.js which seed.spec.js is testing.

I know there is an afterAll hook in Jest, but that will close the connection everywhere which might cause tests to fail incorrectly?

The problem is solved with the --forceExit option, but it gives an error message and doesn't feel like the right way to solve this?

db.js:

const pgp = require('pg-promise')();
const db = pgp(connection);

module.exports = {db, pgp};

seed.spec.js:

require('dotenv').config();
const {pgp} = require('./db');

expect.extend(require('jest-json-schema').matchers);

const schema = require('./schemas');
const generate = require('./generate');
const seed = require('./seed');
const data = generate();

test ('the data returned by the seed function matches the schema', () => {
  return seed(data)
    .then(outputData => {
      expect(outputData).toMatch(schema);
    });
});

P.S. I have seen similar questions, but none of them quite matches my situation.

I need to close a PG-Promise database connection after testing a function in Jest.

This is initialised in one place(db.js) and required everywhere it is needed. In the case of the code below, it is required by seed.js which seed.spec.js is testing.

I know there is an afterAll hook in Jest, but that will close the connection everywhere which might cause tests to fail incorrectly?

The problem is solved with the --forceExit option, but it gives an error message and doesn't feel like the right way to solve this?

db.js:

const pgp = require('pg-promise')();
const db = pgp(connection);

module.exports = {db, pgp};

seed.spec.js:

require('dotenv').config();
const {pgp} = require('./db');

expect.extend(require('jest-json-schema').matchers);

const schema = require('./schemas');
const generate = require('./generate');
const seed = require('./seed');
const data = generate();

test ('the data returned by the seed function matches the schema', () => {
  return seed(data)
    .then(outputData => {
      expect(outputData).toMatch(schema);
    });
});

P.S. I have seen similar questions, but none of them quite matches my situation.

Share Improve this question asked Aug 20, 2018 at 1:36 James WilsonJames Wilson 94213 silver badges31 bronze badges 7
  • but that will close the connection everywhere which might cause tests to fail incorrectly - I'm not sure what you mean. It will close the connection in current suite. This is necessary for the runner to exit normally. – Estus Flask Commented Aug 20, 2018 at 4:02
  • @estus okay so I get this, but problem is that there is only one connection opened in one place at first. To do it this way I'd really need to open a new connection for each teat suite and then close it at the end and then make all the tests run synchronously... What I could really do with is some sort of afterAllTestSuites() hook – James Wilson Commented Aug 20, 2018 at 6:07
  • You have got Jest conception wrong. Each file is a different suite. They run as different processes in parallel. So there are several database connections. afterAll does what it says. – Estus Flask Commented Aug 20, 2018 at 12:10
  • @estus thanks, I get that now - problem is that pg-promise works by making one connection to the database (I think under the hood it may do several, managed ones) and importing that. So I do need a hook that runs after all suites. Luckily I've found one, so am going to make an answer. Thanks for your help(which would have been perfect in other situations!) – James Wilson Commented Aug 20, 2018 at 14:12
  • I don't use pg-promise but I believe that it isn't any different than any other DB adapter that maintains a pool of connections. one connection to the database - it's one connection (pool) per process. Jest spawns several processes and there are several pg-promise instances. They don't know of each other, unless they maintain mon pool in a database - and I'm quite sure they don't. Did afterAll fail for you? Because I'd expect it to be proper solution here. On the other hand, globalTeardown may not work because it's unaware of other pg-promise module instances. – Estus Flask Commented Aug 20, 2018 at 14:16
 |  Show 2 more ments

2 Answers 2

Reset to default 8

As with any other database, the connection should be closed in afterAll.

As the reference states, it's either pgp.end() or db.$pool.end():

afterAll(db.$pool.end);

UPDATE

From pg-promise v10.11.0, you no longer need to shut down the pool explicitely. Instead, you can just set connection option allowExitOnIdle: true, to let process exit when pool is idle.

The closest solution I found to this was using the setupFilesAfterEnv Jest configuration option.

// jest.config.js
module.exports = {
    setupFilesAfterEnv: ['./jest/setup/afterAll']
}

// afterAll.js (path: ./jest/setup/afterAll.js)
const { db } = require('../../src/db')

afterAll(db.$pool.end)

本文标签: javascripthow do I close pgpromise connection in nodejs after all tests have run in jestStack Overflow