不使用 NodeJS 连接到数据库的单元测试 Mysql
Unit test Mysql without connecting to database with NodeJS
我有一个 Conn class,用于使用 AWS IAM 身份验证和 运行 查询连接到 MySQL 数据库。我已经编写了 class 并且它工作正常,但是我在不访问数据库的情况下尝试测试它时遇到了很多困难。
这是康恩 Class:
const AWS = require('aws-sdk');
const mysql = require("mysql2/promise");
class Conn {
constructor(options = {}) {
this.options = options;
}
async getPool() {
return mysql.createPool(this.options);
}
setToken () {
this.signer = new AWS.RDS.Signer({
region: 'us-east-1', // example: us-east-2
hostname: this.options.host,
port: 3306,
username: this.options.user
});
this.token = this.signer.getAuthToken({
username: this.options.user
});
}
async setConnection () {
this.dbOptions = {
host : this.options.host,
user : this.options.user,
ssl: 'Amazon RDS',
password: this.token,
authPlugins: {
mysql_clear_password: () => () => Buffer.from(this.token + '[=11=]')
}
};
this.pool = await this.getPool(this.dbOptions);
this.conn = await this.pool.getConnection();
}
async executeQuery () {
this.dbResult = await this.conn.query("select 1 + 1 as solution");
this.conn.release();
}
}
module.exports = {
Conn: Conn
}
我在这里尝试使用 sinon 测试 Conn.executeQuery
函数:
const { handler } = require("../src/conn");
const sinon = require("sinon");
const {expect: expects} = require("chai");
const connection = require('../src/conn');
describe("conn", () => {
afterEach(() => {
sinon.restore();
});
it("should test conn.executeQuery", async () => {
const connStub = { query: sinon.stub().resolves({ rowCount: 1 }), release: sinon.stub() };
const poolStub = { getConnection: sinon.stub().resolves(connStub) };
const pool = {getPool: sinon.stub().resolves(poolStub)};
const conn = new connection.Conn();
await conn.setConnection();
const actual = await conn.executeQuery()
expects(actual).to.be.eql({ rowCount: 1 });
sinon.assert.calledWith(connStub.query, "select 1 + 1 as solution");
sinon.assert.calledOnce(connStub.release);
});
});
不幸的是,这段代码产生的都是错误,例如
Error: connect ECONNREFUSED 127.0.0.1:3306
如何使用 sinon
测试 Conn.executeQuery
函数而不访问数据库?
单元测试解决方案:
Conn.js
:
const mysql = require('mysql2/promise');
class Conn {
constructor(options = {}) {
this.options = options;
}
async getPool() {
return mysql.createPool(this.options);
}
async setConnection() {
this.dbOptions = {
host: this.options.host,
user: this.options.user,
ssl: 'Amazon RDS',
password: this.token,
authPlugins: {
mysql_clear_password: () => () => Buffer.from(this.token + '[=10=]'),
},
};
this.pool = await this.getPool(this.dbOptions);
this.conn = await this.pool.getConnection();
}
async executeQuery() {
this.dbResult = await this.conn.query('select 1 + 1 as solution');
this.conn.release();
}
}
module.exports = { Conn };
Conn.test.js
:
const { Conn } = require('./Conn');
const sinon = require('sinon');
const mysql = require('mysql2/promise');
describe('64112250', () => {
afterEach(() => {
sinon.restore();
});
it('should test conn.executeQuery', async () => {
const poolStub = {
getConnection: sinon.stub().returnsThis(),
query: sinon.stub().returnsThis(),
release: sinon.stub(),
};
const createPoolStub = sinon.stub(mysql, 'createPool').returns(poolStub);
const conn = new Conn();
await conn.setConnection();
await conn.executeQuery();
sinon.assert.calledOnce(createPoolStub);
sinon.assert.calledOnce(poolStub.getConnection);
sinon.assert.calledWithExactly(poolStub.query, 'select 1 + 1 as solution');
sinon.assert.calledOnce(poolStub.release);
});
});
带有覆盖率报告的单元测试结果:
64112250
✓ should test conn.executeQuery
1 passing (24ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 81.82 | 100 | 66.67 | 90 |
Conn.js | 81.82 | 100 | 66.67 | 90 | 19
----------|---------|----------|---------|---------|-------------------
我有一个 Conn class,用于使用 AWS IAM 身份验证和 运行 查询连接到 MySQL 数据库。我已经编写了 class 并且它工作正常,但是我在不访问数据库的情况下尝试测试它时遇到了很多困难。
这是康恩 Class:
const AWS = require('aws-sdk');
const mysql = require("mysql2/promise");
class Conn {
constructor(options = {}) {
this.options = options;
}
async getPool() {
return mysql.createPool(this.options);
}
setToken () {
this.signer = new AWS.RDS.Signer({
region: 'us-east-1', // example: us-east-2
hostname: this.options.host,
port: 3306,
username: this.options.user
});
this.token = this.signer.getAuthToken({
username: this.options.user
});
}
async setConnection () {
this.dbOptions = {
host : this.options.host,
user : this.options.user,
ssl: 'Amazon RDS',
password: this.token,
authPlugins: {
mysql_clear_password: () => () => Buffer.from(this.token + '[=11=]')
}
};
this.pool = await this.getPool(this.dbOptions);
this.conn = await this.pool.getConnection();
}
async executeQuery () {
this.dbResult = await this.conn.query("select 1 + 1 as solution");
this.conn.release();
}
}
module.exports = {
Conn: Conn
}
我在这里尝试使用 sinon 测试 Conn.executeQuery
函数:
const { handler } = require("../src/conn");
const sinon = require("sinon");
const {expect: expects} = require("chai");
const connection = require('../src/conn');
describe("conn", () => {
afterEach(() => {
sinon.restore();
});
it("should test conn.executeQuery", async () => {
const connStub = { query: sinon.stub().resolves({ rowCount: 1 }), release: sinon.stub() };
const poolStub = { getConnection: sinon.stub().resolves(connStub) };
const pool = {getPool: sinon.stub().resolves(poolStub)};
const conn = new connection.Conn();
await conn.setConnection();
const actual = await conn.executeQuery()
expects(actual).to.be.eql({ rowCount: 1 });
sinon.assert.calledWith(connStub.query, "select 1 + 1 as solution");
sinon.assert.calledOnce(connStub.release);
});
});
不幸的是,这段代码产生的都是错误,例如
Error: connect ECONNREFUSED 127.0.0.1:3306
如何使用 sinon
测试 Conn.executeQuery
函数而不访问数据库?
单元测试解决方案:
Conn.js
:
const mysql = require('mysql2/promise');
class Conn {
constructor(options = {}) {
this.options = options;
}
async getPool() {
return mysql.createPool(this.options);
}
async setConnection() {
this.dbOptions = {
host: this.options.host,
user: this.options.user,
ssl: 'Amazon RDS',
password: this.token,
authPlugins: {
mysql_clear_password: () => () => Buffer.from(this.token + '[=10=]'),
},
};
this.pool = await this.getPool(this.dbOptions);
this.conn = await this.pool.getConnection();
}
async executeQuery() {
this.dbResult = await this.conn.query('select 1 + 1 as solution');
this.conn.release();
}
}
module.exports = { Conn };
Conn.test.js
:
const { Conn } = require('./Conn');
const sinon = require('sinon');
const mysql = require('mysql2/promise');
describe('64112250', () => {
afterEach(() => {
sinon.restore();
});
it('should test conn.executeQuery', async () => {
const poolStub = {
getConnection: sinon.stub().returnsThis(),
query: sinon.stub().returnsThis(),
release: sinon.stub(),
};
const createPoolStub = sinon.stub(mysql, 'createPool').returns(poolStub);
const conn = new Conn();
await conn.setConnection();
await conn.executeQuery();
sinon.assert.calledOnce(createPoolStub);
sinon.assert.calledOnce(poolStub.getConnection);
sinon.assert.calledWithExactly(poolStub.query, 'select 1 + 1 as solution');
sinon.assert.calledOnce(poolStub.release);
});
});
带有覆盖率报告的单元测试结果:
64112250
✓ should test conn.executeQuery
1 passing (24ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 81.82 | 100 | 66.67 | 90 |
Conn.js | 81.82 | 100 | 66.67 | 90 | 19
----------|---------|----------|---------|---------|-------------------