In my app I have a process that involves CRUD operations on a mssql database.
For the connection to the db I'm using node-mssql
and for establishing the connection itself I'm basically following the official documentation at https://tediousjs.github.io/node-mssql/ under the section Advanced Pool Management
The TS code for getting the Connection Pool, therefore, looks like this:
import {ConnectionPool, config} from 'mssql';
const pools = new Map();
/**
* Get or create a pool. If a pool doesn't exist the config must be provided.
* If the pool does exist the config is ignored (even if it was different to the one provided
* when creating the pool)
*
* @param {string} name
* @param [config]
* @return {Promise.<ConnectionPool>}
*/
export function getAc3ConnectionPool (name:string, config:config) {
if (!pools.has(name)) {
if (!config) {
throw new Error('Pool does not exist');
}
const pool = new ConnectionPool(config);
// automatically remove the pool from the cache if `pool.close()` is called
const close = pool.close.bind(pool);
pool.close = () => {
pools.delete(name);
return close();
};
pools.set(name, pool.connect());
}
return pools.get(name);
}
/**
* Closes all the pools and removes them from the store
*
* @return {Promise<ConnectionPool[]>}
*/
export function closeAll() {
return Promise.all(Array.from(pools.values()).map((connect) => {
return connect.then((pool: ConnectionPool) => pool.close());
}));
}
Now, I like to write a test with sinon where I stub the connection (ac3Connection
) and everything that comes afterwards.
To be honest, I don't have much or any expierence in writing tests or using sinon let alone.
This is what I came up with based on this example for jest (https://stackoverflow.com/a/69399560/3856569) trying to convert it.
For spacing reasons, I'm skipping all the other imports.
import * as ac3Connection from '../../../util/connectionsManagers/ac3/ac3Connection';
describe('EmployeeDiscountController', function () {
let sequelize!: Sequelize;
let user!: User;
let mockUIRequest!: Request<any, any, EmployeeDiscountMasterViewDataRequestBody>;
let mockUIResponse!: any;
let mockDBConnect!: any;
let mockDBRequest!: any;
let redirectCalled: boolean | string = false;
let dao!: EmployeeDiscountDao;
let service!: EmployeeDiscountService;
let controller!: EmployeeDiscountController;
let renderResultPromise!: Promise<any>;
beforeEach(async function() {
const models: ModelCtor[] = [User, JobPostingsMarket];
sequelize = sequelizeFor(...models);
await sequelize.sync();
user = await User.create({
provider: 'foo',
googleId: 'foo',
emailAdress: 'foo@foo.foo',
name: 'foo',
lastLogin: new Date()
});
mockUIRequest = {user} as Request<any, any, EmployeeDiscountMasterViewDataRequestBody>;
mockUIResponse = {
redirect: (target: string) => {
redirectCalled = target;
}
} as any;
mockDBConnect = sinon.stub().callsFake(() => {
return Promise.resolve({transaction: this._mockTransaction});
});
mockDBRequest = sinon.stub().returns({
input: this._mockInput,
query: this._mockQuery
});
renderResultPromise = new Promise<any>((resolve, reject) => {
mockUIResponse.render = (url: string, data: any) => {
resolve(data);
};
});
dao = new EmployeeDiscountDao();
service = new EmployeeDiscountService();
controller = new EmployeeDiscountController();
sinon.stub(ac3Connection, 'getAc3ConnectionPool').returns({
ConnectionPool: sinon.stub().returns({
request: mockDBRequest,
connect: mockDBConnect
})
});
});
afterEach(async function () {
sinon.restore();
});
it('can create an employee discount', async function () {
const body: EmployeeDiscountMasterViewDataRequestBody = {
firstname: 'foo',
cardNumber: '99900000101',
organization: 'foo' as unknown as readonly String[],
currentOrganization: undefined,
surname: 'foo'
};
mockUIRequest.body = body;
await controller.create(mockUIRequest, mockUIResponse);
const result = await renderResultPromise;
expect(result).to.have.property('employeeId');
//expect(redirectCalled).to.eq(getMasterDataViewPath(createResponse.employeeId.toString()));
});
});
Unfortunately, I'm getting the following error:
ConnectionError: Failed to connect to :1433 - Could not connect (sequence)
at Connection.<anonymous> (C:\xxx\node_modules\mssql\lib\tedious\connection-pool.js:68:17)
at Object.onceWrapper (node:events:628:26)
at Connection.emit (node:events:513:28)
at Connection.emit (node:domain:489:12)
at Connection.socketError (C:\Users\xxx\node_modules\tedious\lib\connection.js:1290:12)
at C:\Users\xxx\node_modules\tedious\lib\connection.js:1116:21
at SequentialConnectionStrategy.connect (C:\Users\xxx\node_modules\tedious\lib\connector.js:87:14)
at C:\Users\xxx\node_modules\tedious\lib\connector.js:164:67
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ESOCKET',
I suppose it is not mocking the establishment of the connection but I don't know at which place to change the code.
Thanks for your help!