TypeORM createConnection hangs in Jest - jestjs

When I'm trying to create a TypeORM connection to a local postgres database in a beforeAll Jest hook, TypeORM's createConnection keeps hanging for indefinite amount of time.
I don't want to have it globally because the majority of the tests don't need this database connection.
jest.config.ts
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
example.spec.ts
let conn;
describe('GET /healthz', () => {
beforeAll(async () => {
conn = await createConnection({
name: 'default',
type: 'postgres',
host: 'localhost',
port: 5433, // <- not a typo, I tested on both 5433 and 5432
database: 'test-local',
username: 'user',
password: 'pwd',
synchronize: true,
logging: true,
});
});
afterEach(async () => {
// omitted, but truncates all tables after every test
});
afterAll(async () => {
await conn.close();
});
it('should be true', () => {
expect(true).toBe(true);
});
});
Output of running jest with --detectOpenHandles:
However when I copy exactly these connection options in my normal application, it works correctly without any errors. And also in my jest it doesn't throw any errors so I'm pretty lost on what's going on here. I tried it in globalSetup before, but even there it just hangs. It just doesn't get past the createConnection. Any ideas or suggestions is much appreciated!

Altough the --detectOpenHandle pointed at the createDbConnection of TypeORM, it was actually a totally different thing that hanged.
It was very misleading, but I started cronjobs somewhere in the express app, which were hanging instead of the TypeORM createConnection.

Related

Connection to postgresql db from node js

I'm tyring to make a connection from my nodejs script to my db connection, but seems like there is a suspicius issue i'm not able to figure out.
At the moment, this is my code:
const { Pool } = require('pg');
const pool = new Pool({
user: 'user',
host: '192.168.1.xxx',
database: 'database',
password: 'password',
port: 5432,
});
pool.on('error', (err, client) => {
console.error('Error:', err);
});
const query = `SELECT * FROM users`;
pool.connect()
.then((client) => {
client.query(query)
.then(res => {
for (let row of res.rows) {
console.log(row);
}
})
.catch(err => {
console.error(err);
});
})
.catch(err => {
console.error(err);
});
The issue seems to be in pool.connect(), but i can't understand what i'm missing because i got no errors in the log. I've installed pg module in the directory of my project with npm install --prefix pg and i know modules are loaded correctly.
I edited postgresql.conf:
# - Connection Settings -
listen_addresses = '*'
and pg_hba.conf
host database user 192.168.1.0/24 md5
to make the database reachable via lan and seems liek it works, because i'm able to connect successfully with apps like DBeaver...but i can't with NodeJS.
It's possible there is some kind of configuration i've to active?

Exception handling not working for PG npm package

I installed "pg": "^8.0.2" and created the database.js file with database credentials. But no matter what go wrong it never enters in the catch block to show error. Instead it always logs connected to the database. Can anyone point out what I'm doing wrong. Thank You!
Database.js
const Pool = require('pg').Pool;
const pool = new Pool({
user: 'roothjk',
host: 'localhost',
database: 'sf',
password: 'admin',
port: 5432
});
try {
pool.connect()
console.log('connected to the db');
} catch (e) {
console.log('Error connecting to db');
}
connect returns a Promise, and then you move to the next statement. Instead, you should use the then and cath methods:
pool.connect()
.then(c => console.log('connected to the db'))
.catch(e => console.log('Error connecting to db'));

Automated Testing with Databases

I'm fairly new to automated testing and was wondering how I should go about writing tests for the database. The project I'm working on right now is running PostgreSQL with Sequelize as the ORM on a Node.JS environment. If it matters, I'm also using Jest as the testing library right now.
In my app I use a config module to control configuration settings for different environments. When running tests the process.env.APP_ENV is set to test, and it will set the dialect to sqlite. Note that you will not have any data or data persistence, so you will need to populate it with all the data needed for your tests.
Include sqlite3
yarn add -D sqlite3
or
npm i -D sqlite3
Config
module.exports = {
database: {
name: 'dbname',
user: 'user',
password: 'password',
host: 'host',
// Use "sqlite" for "test", the connection settings above are ignored
dialect: process.env.APP_ENV === 'test' ? 'sqlite' : 'mysql',
},
};
Database/Sequelize
// get our config
const config = require('../config');
// ... code
const instance = new Sequelize(
config.database.name,
config.database.user,
config.database.password,
{
host: config.database.host,
// set the dialect, will be "sqlite" for "test"
dialect: config.database.dialect,
}
);
Test Class (Mocha)
const TestUtils = require('./lib/test-utils');
describe('Some Tests', () => {
let app = null;
// run before the tests start
before((done) => {
// Mock up our services
TestUtils.mock();
// these are instantiated after the mocking
app = require('../server');
// Populate redis data
TestUtils.populateRedis(() => {
// Populate db data
TestUtils.syncAndPopulateDatabase('test-data', () => {
done();
});
});
});
// run code after tests have completed
after(() => {
TestUtils.unMock();
});
describe('/my/route', () => {
it('should do something', (done) => {
return done();
});
});
});
Run Tests
APP_ENV=test ./node_modules/.bin/mocha
You could use ENV variables in other ways to set the dialect and connection parameters as well - the above is just an example based on what we have done with a lot of supporting code.
If you're not doing anything particularly complicated on the DB side, take a look at pg-mem:
https://swizec.com/blog/pg-mem-and-jest-for-smooth-integration-testing/
https://github.com/oguimbal/pg-mem
It's really cool in that it tests actual PG syntax and can pick up a bunch of errors that using a different DB or mock DB won't pick up. However, it's not a perfect implementation and missing a bunch of features (e.g. triggers, decent "not exists" handling, lots of functions) some of which are easy to work around with the hooks provided and some aren't.
For me, having the test DB initialized with the same schema initialization scripts as the real DB is a big win.

Jest cannot handle the sequelize.sync() promise

I have this test file running with Jest:
test('this works', () => {
Promise.resolve();
});
test('this also works', (done) => {
setTimeout(done, 100);
});
test('this does not work', () => {
return models.sequelize.sync({force: true, logging: false});
});
test('this also does not work', (done) => {
models.sequelize.sync({force: true, logging: false}).then(() => done());
});
Something is either weird with Sequelize.js or Jest. Ideas?
To clarify: It's not I'm getting failing tests, all 4 tests are green. The latter two will get the database reset, but the Jest process will forever hang even after all test ran. Jest will say: 4 passed, just I have to manually quit with Ctrl + C.
As mentioned in this Github issue: https://github.com/sequelize/sequelize/issues/7953
The sync method actually will only return when the connection idles eventually, so the solution is to:
models.sequelize.sync({force: true, logging: false}).then(() => {
models.sequelize.close();
});

Sequelize connection and logging issues

I am trying to use Sequelize to connect with a SQL Server 2012 database. When my connection string was clearly wrong, I was seeing ECONN REFUSED messages and timeout. Now, I am not getting any response, despite logging on success and fail, per this code:
import * as Sequelize from 'sequelize';
-- connection string redacted
let seqConn = new Sequelize("mssql://**;Initial Catalog=**;Persist Security Info=True;Integrated Security=SSPI; User ID=**; Password=**")
seqConn
.authenticate()
.then(function(err) {
console.log('Connection has been established successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the database:', err);
});
I was previously using the syntax:
let seqConn = new Sequelize("DB", "Username", "Password",
{
dialect: 'mssql',
dialectOptions: {
instanceName: 'dev'
},
host: '**'
};
But I couldn't find a setting for integrated security or other fancy SQL Server things.
Regardless, my current connection string isn't erroring. But also, it is not saying the connection was established.
I tried passing my seqConn to a model to use it to retrieve a model:
getModel(seqConn): void {
console.log("Getting");
var model = seqConn.define("dbo.Model", {
modelID: Sequelize.INTEGER,
modelNo: Sequelize.INTEGER,
modelName: Sequelize.STRING(50),
modelAge: Sequelize.DATE
});
seqConn.sync().then(function() {
model.findOne()
.then( function (modelRes){
console.log("got a result!?");
console.log(modelRes.get("modelName"));
})
.catch( function (error){
console.log("it didn't work :( ");
});
});
console.log('after getter');
return;
}
I'm not confident that this is the right way to use sequelize, and I'm still establishing my project structure, but for now I expect to either see a "got a result" or an error, but nothing is logging here from either the then() or the catch(). The before/after getter logs are logging fine.
I have considered that it takes a long time to connect, but my IT says that he saw my successful connection in our SQL logs, and previously I was getting timeouts in about 15,000 ms, I think.
The problem was solved by including another NPM module: `sequelize-msnodesqlv8'
And then the code to connect to Sequelize looked like:
var Sequelize = require('sequelize');
var seqConn = new Sequelize({
dialect: 'mssql',
dialectModulePath: 'sequelize-msnodesqlv8',
dialectOptions: {
connectionString: 'Driver={SQL Server Native Client 11.0};[REDACTED]'
}
});
seqConn
.authenticate()
.then(function(err) {
console.log('Connection has been established successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the database:', err);
});

Resources