使用Jest测试通过Tedious连接到SQL Server的NodeJS函数,抛出错误:无法重新定义属性:Connec



尝试使用Jest测试Tedious连接器函数。

在代码文件db_server.js中,我在下面有这个函数,它按预期工作。

const AWS = require('aws-sdk')
const tedious = require('tedious')
const Request = require('tedious').Request;
const Connection = require('tedious').Connection;
exports.execSQLCmd = async function (conn_store, cmd) {
let config = await exports.getParameter(conn_store)
let conn_cfg = JSON.parse(config)
//connect
const connection = new Connection(conn_cfg);
connection.on('connect', function (err) {
if (err) {
console.log('CONNECTION ERROR: ' + err);
}
console.log('CONNECTED TO: ' + conn_cfg.server);
executeStatement();
});
connection.connect();
//execute the sql command   
let result = '';
function executeStatement() {
let request = new Request(cmd, function (err) {
if (err) {
console.log('REQUEST ERROR: ' + err);
}
});
//add three event hooks to the request
request.on('row', function (columns) {
columns.forEach(function (column) {
result += (column.value === null ? '' : column.value) + ',';
});
result = result.replace(/,$/, 'rn')
});
request.on('done', function (rowCount, more) {
console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
});
request.on('requestCompleted', function (rowCount, more) {
connection.close();
console.log('CONNECTION TO SERVER CLOSED');
});
connection.execSql(request);
}
return result;
}
exports.Request = Request
exports.Connection = Connection
exports.tedious = tedious

在测试文件index.spec.js中,我有以下测试:

describe('Test execSQLCmd', () => {
const server = require("../src/db_server.js")
afterEach(() => {
jest.restoreAllMocks();
});


test('should query sql', async () => {
server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}') 
server.execSQLCmd = jest.fn().mockReturnThis()
const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
connect: () => {},
on: (connect, cb) => cb(),
close: () => {},
execSql: () => {}
})));
const TedRequest = jest.spyOn(server.tedious, 'Request').mockReturnValue(jest.fn(() => ({
constructor: (sqlString, cb) => cb('err', null, null),
on: [
(row, cb)=> cb('columns'),
(done, cb)=> cb('rowCount', 'more'),
(requestCompleted, cb) => cb('rowCount', 'more')
]
})));

let exec = server.execSQLCmd("/pstore/name", "select 1")
expect(TedConnect).toBeCalledTimes(1)
expect(TedRequest).toBeCalledTimes(1)

})

})

当我尝试运行测试时,我会得到以下错误:

测试execSQLCmd›应查询sql

TypeError: Cannot redefine property: Connection
at Function.defineProperty (<anonymous>)
298 |     server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}')
299 |     server.execSQLCmd = jest.fn().mockReturnThis()
> 300 |     const TedConnect = jest.spyOn(server.tedious, 'Connection').mockReturnValue(jest.fn(() => ({
|                             ^
301 |                  connect: () => {},
302 |                  on: (connect, cb) => cb(),
303 |                  close: () => {},
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:826:16)
at Object.<anonymous> (__tests__/index.spec.js:300:29)
Test Suites: 1 failed, 1 total
"tedious": "^14.1.0"
"jest": "^26.6.3",

我不明白为什么这次考试不及格。

感谢任何帮助,谢谢!

编辑

在以下测试更改后未发生上述错误:

test('should query sql', async () => {
server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}') 
server.execSQLCmd = jest.fn().mockReturnThis()
server.Connection = jest.fn().mockReturnValue(jest.fn(() => ({
connect: () => {},
on: (connect, cb) => cb(),
close: () => {},
execSql: () => {}
}))) 
server.Request = jest.fn().mockReturnValue(jest.fn(() => ({
constructor: (sqlString, cb) => cb('err', null, null),
//addParameter: (name, type, value) => {},
on: [
(row, cb)=> cb('columns'),
(done, cb)=> cb('rowCount', 'more'),
(requestCompleted, cb) => cb('rowCount', 'more')
]
}))) 
let exec = server.execSQLCmd("/pstore/name", "select 1")
expect(server.Connection).toBeCalledTimes(1)
expect(server.Request).toBeCalledTimes(1)
})

然而,现在server.execSQLCmd没有运行,我无法通过调试进入它,它立即存在并返回一个大的mock对象。

有人看到我做错了什么吗?

谢谢!

exports.execSQLCmd = async function (conn_store, cmd) {

let config = await exports.getParameter(conn_store)
let conn_cfg = JSON.parse(config)
//connect
exports.connect_exec(conn_cfg, cmd);    
return result;
}
function connect_exec(conn_cfg, cmd) {
const connection = exports.get_connection(conn_cfg);
exports.on_connect(connection, cmd);
connection.connect();
return connection;
}
function on_connect(connection, cmd) {
connection.on('connect', function (err) {
if (err) {
console.log('CONNECTION ERROR: ' + err);
}
console.log('CONNECTED');
exports.execute_statement(connection, cmd);
});
}
function get_connection(conn_cfg) {
return new Connection(conn_cfg);
}
function execute_statement(connection, cmd) {
let request = exports.get_request(connection, cmd);
connection.execSql(request);
}
function get_request(connection, cmd) {
let request = new Request(cmd, function (err) {
if (err) {
console.log('REQUEST ERROR: ' + err);
}
});
//add three event hooks to the request
request.on('row', function (columns) {
columns.forEach(function (column) {
result += (column.value === null ? '' : column.value) + ',';
});
result = result.replace(/,$/, 'rn');
});
request.on('done', function (rowCount, more) {
console.log('SQL COMMAND COMPLETED: ' + rowCount + ' rows returned');
});
request.on('requestCompleted', function (rowCount, more) {
connection.close();
console.log('CONNECTION TO SERVER CLOSED');
});
return request;
}
exports.AWS = AWS;
exports.connect_exec = connect_exec
exports.execute_statement = execute_statement
exports.get_request = get_request
exports.get_connection = get_connection
exports.on_connect = on_connect

这是我的测试:

describe('Test execSQLCmd', async () => {
const server = require("../src/opportunity/db_server.js")

afterEach(() => {
jest.restoreAllMocks();
});
test('should query sql', async () => {
server.getParameter = jest.fn().mockReturnValue('{"xxx":123,"yyy":"hello"}') 

server.get_connection = jest.fn().mockReturnValue({
connect: () => {},
on: (connect, cb) => cb(),
close: () => {} ,
execSql: () => {}
}) 
server.get_request = jest.fn().mockReturnValue({
constructor: (sqlString, cb) => cb('err', null, null),
on: [
(row, cb)=> cb('columns'),
(done, cb)=> cb('rowCount', 'more'),
(requestCompleted, cb) => cb('rowCount', 'more')
]
})

await server.execSQLCmd("/pstore/name", "select 1")      
expect(server.get_connection).toHaveBeenCalled()
expect(server.get_request).toHaveBeenCalled()
})
}) 

我花了一天的时间来编写主要功能的所有代码,比这里还多。

我花了2.5天的时间才搞清楚这个测试。愚蠢的

最新更新