使用 sinon 模拟无服务器-mysql
Mocking serverless-mysql using sinon
我正在尝试测试使用 AWS SAM 创建的 AWS lambda 函数 (node.js)。我的函数使用 npm 模块 serverless-mysql
连接到 Aurora。以下是我的 lambda 函数的相关部分:
const connection = require('serverless-mysql')({
config: {
host : process.env.DB_HOST,
user : process.env.DB_USER,
password : process.env.DB_PASSWORD
}
});
exports.lambdaHandler = async (event, context) => {
try {
const name = event.pathParameters.name;
const rows = await connection.query('SELECT * FROM users WHERE name = ?', [name]);
await connection.end()
const user = rows[0];
return {
'statusCode': 200,
'body': JSON.stringify({
firstName: user.first_name,
lastName: user.last_name,
bk: user.bk,
team: user.current_team
})
}
} catch (err) {
console.log(err);
return err;
}
};
我正在尝试通过模拟 serverless-mysql
依赖项来对此进行测试,但我目前无法这样做。我的测试如下所示:
const app = require('../../app.js');
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const event = {
pathParameters: {
name: 'johndoe'
}
}
var context;
var successConnectionObject = {
connect: function() {
return Promise.resolve();
},
query: function(sqlQuery, params) {
return Promise.resolve('');
},
end: function() {}
}
var mysql = require('serverless-mysql');
var stub = sinon.stub(mysql, 'connect').returns(successConnectionObject);
describe('Tests', function () {
it('verifies successful response', async () => {
const result = await app.lambdaHandler(event, context);
expect(result).to.be.an('object');
expect(result.statusCode).to.equal(200);
mock.verify();
mock.restore();
});
});
但是,这个returns出现以下错误:
TypeError: Cannot stub non-existent own property connect
我相信这是因为 mysql
没有实例化。所以我将行 var mysql = require('serverless-mysql');
替换为:
var mysql = require('serverless-mysql')();
不幸的是,这会导致以下错误:
AssertionError: expected [Error: Error: self signed certificate in certificate chain] to be an object
所以似乎调用了真正的 serverless-mysql
模块的 connect()
方法。
如何使用 sinon 正确模拟 serverless-mysql
?
require('serverless-mysql')
returns 一个 函数 那个 returns 一个 不同的值 每次都是调用,因此模拟 one 调用结果的属性不会影响 different 调用的返回值。
这意味着您必须模拟函数本身,这意味着模拟整个模块。
sinon
没有提供模拟整个模块的方法,因此您必须为该部分使用其他东西。
这是一个使用 proxyquire
模拟 serverless-mysql
模块的工作测试:
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const proxyquire = require('proxyquire');
const event = {
pathParameters: {
name: 'johndoe'
}
}
var context;
var successConnectionObject = {
connect: function () {
return Promise.resolve();
},
query: function (sqlQuery, params) {
return Promise.resolve([{
first_name: 'first',
last_name: 'last',
bk: 'bk',
current_team: 'team'
}]);
},
end: function () { }
}
const stub = sinon.stub().returns(successConnectionObject);
const app = proxyquire('../../app.js', { 'serverless-mysql': stub });
describe('Tests', function () {
it('verifies successful response', async () => {
const result = await app.lambdaHandler(event, context);
expect(result).to.be.an('object'); // Success!
expect(result.statusCode).to.equal(200); // Success!
sinon.assert.calledWithExactly(stub, {
config: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
}
}); // Success!
});
});
我正在尝试测试使用 AWS SAM 创建的 AWS lambda 函数 (node.js)。我的函数使用 npm 模块 serverless-mysql
连接到 Aurora。以下是我的 lambda 函数的相关部分:
const connection = require('serverless-mysql')({
config: {
host : process.env.DB_HOST,
user : process.env.DB_USER,
password : process.env.DB_PASSWORD
}
});
exports.lambdaHandler = async (event, context) => {
try {
const name = event.pathParameters.name;
const rows = await connection.query('SELECT * FROM users WHERE name = ?', [name]);
await connection.end()
const user = rows[0];
return {
'statusCode': 200,
'body': JSON.stringify({
firstName: user.first_name,
lastName: user.last_name,
bk: user.bk,
team: user.current_team
})
}
} catch (err) {
console.log(err);
return err;
}
};
我正在尝试通过模拟 serverless-mysql
依赖项来对此进行测试,但我目前无法这样做。我的测试如下所示:
const app = require('../../app.js');
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const event = {
pathParameters: {
name: 'johndoe'
}
}
var context;
var successConnectionObject = {
connect: function() {
return Promise.resolve();
},
query: function(sqlQuery, params) {
return Promise.resolve('');
},
end: function() {}
}
var mysql = require('serverless-mysql');
var stub = sinon.stub(mysql, 'connect').returns(successConnectionObject);
describe('Tests', function () {
it('verifies successful response', async () => {
const result = await app.lambdaHandler(event, context);
expect(result).to.be.an('object');
expect(result.statusCode).to.equal(200);
mock.verify();
mock.restore();
});
});
但是,这个returns出现以下错误:
TypeError: Cannot stub non-existent own property connect
我相信这是因为 mysql
没有实例化。所以我将行 var mysql = require('serverless-mysql');
替换为:
var mysql = require('serverless-mysql')();
不幸的是,这会导致以下错误:
AssertionError: expected [Error: Error: self signed certificate in certificate chain] to be an object
所以似乎调用了真正的 serverless-mysql
模块的 connect()
方法。
如何使用 sinon 正确模拟 serverless-mysql
?
require('serverless-mysql')
returns 一个 函数 那个 returns 一个 不同的值 每次都是调用,因此模拟 one 调用结果的属性不会影响 different 调用的返回值。
这意味着您必须模拟函数本身,这意味着模拟整个模块。
sinon
没有提供模拟整个模块的方法,因此您必须为该部分使用其他东西。
这是一个使用 proxyquire
模拟 serverless-mysql
模块的工作测试:
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const proxyquire = require('proxyquire');
const event = {
pathParameters: {
name: 'johndoe'
}
}
var context;
var successConnectionObject = {
connect: function () {
return Promise.resolve();
},
query: function (sqlQuery, params) {
return Promise.resolve([{
first_name: 'first',
last_name: 'last',
bk: 'bk',
current_team: 'team'
}]);
},
end: function () { }
}
const stub = sinon.stub().returns(successConnectionObject);
const app = proxyquire('../../app.js', { 'serverless-mysql': stub });
describe('Tests', function () {
it('verifies successful response', async () => {
const result = await app.lambdaHandler(event, context);
expect(result).to.be.an('object'); // Success!
expect(result.statusCode).to.equal(200); // Success!
sinon.assert.calledWithExactly(stub, {
config: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
}
}); // Success!
});
});