如何使用 Jest 测试 express + dynamodb?
How to test express + dynamodb using Jest?
我是 Jest 和单元测试的新手,我在 AWS.Express 的无服务器(Lambda)上部署了一个 express API api 使用 dynamodb 进行 crud 操作
注意:- 我的 api 是基于 express 的,而不仅仅是普通节点,因为在 jest website 上他们告诉了普通 nodejs
我能够对不使用的方法进行单元测试 dynamodb.However 对于使用 dynamodb 的方法,它失败了,据我所知,这与 dynamodb 是远程的有关,因为 app.js 中的代码对应于使用 lambda 在 aws 上托管的 dyanmo 数据库。
我该怎么做?
注意:- 我的 api 是基于 express 而不是简单的节点
const isUrl = require('is-url');
const AWS = require('aws-sdk');
const { nanoid } = require('nanoid/async');
const express = require('express');
const router = express.Router();
const dynamoDb = new AWS.DynamoDB.DocumentClient();
// URL from users
router.post('/', async (req, res, next) => {
// urlId contains converted short url characters generated by nanoid
const urlId = await nanoid(8);
const { longUrl } = req.body;
// Veryfying url Format using isUrl, this return a boolean
const checkUrl = isUrl(longUrl);
if (checkUrl === false) {
res.status(400).json({ error: 'Invalid URL, please try again!!!' });
}
const originalUrl = longUrl;
const userType = 'anonymous'; // user type for anonymous users
const tableName = 'xxxxxxxxxxxxx'; // table name for storing url's
const anonymousUrlCheckParams = {
TableName: tableName,
Key: {
userId: userType,
originalUrl,
},
};
dynamoDb.get(anonymousUrlCheckParams, (err, data) => {
const paramsForTransaction = {
TransactItems: [
{
Put: {
TableName: tableName,
Item: {
userId: userType,
originalUrl,
convertedUrl: `https://xxxxxxxxxxxxxxxx/${urlId}`,
},
},
},
{
Put: {
TableName: tableName,
Item: {
userId: urlId,
originalUrl,
},
ConditionExpression: 'attribute_not_exists(userId)',
},
},
],
};
if (err) {
console.log(err);
res
.status(500)
.json({ error: 'Unknown Server Error, Please Trimify Again!' });
} else if (Object.keys(data).length === 0 && data.constructor === Object) {
dynamoDb.transactWrite(paramsForTransaction, async (error) => {
if (error) {
// err means converted value as userId is repeated twice.
console.log(error);
res
.status(500)
.json({ error: 'Unknown Server Error, Please trimify again. ' });
} else {
res.status(201).json({
convertedUrl: `https://xxxxxxxxxxxx/${urlId}`,
});
}
});
} else {
res.status(201).json({
convertedUrl: data.Item.convertedUrl,
});
}
});
});
module.exports = router;
我的test.js
const request = require('supertest');
const app = require('../app');
test('Should convert url from anonymous user ', async () => {
await request(app)
.post('/anon-ops/convert')
.send({
longUrl: 'https://google.com',
})
.expect(201);
});
首先,如果您想进行单元测试。您是否使用 express js 并不重要,因此,jest 网站上的示例和信息非常有效,可以帮助您上路。
进行单元测试的难易程度主要取决于您构建代码的方式。例如,您可以将所有 express js 特定代码保存在单独的文件中,然后仅在单元测试期间实例化包含实际业务逻辑(有些人可能称为服务层)的文件。这至少是您可以让自己更轻松的一种方式。使用函数式方法还可以让您的代码更易于测试,或者至少可以使用依赖注入,因此您可以在测试期间交换依赖项,以便单独测试某些功能。
谈到 DynamoDB,您有两个选择。模拟或 运行 本地版本。
您可以使用 jest mocks or using a mocking library such as sinon 模拟您正在调用的特定函数。选择哪个主要是个人喜好。
第二个选项是运行一个local version of DynamoDB in a docker container。这也有验证您对 DynamoDB 服务的实际调用的好处(您可以通过验证模拟来完成,但在验证中很容易出错),但是,设置起来更麻烦,您的测试将是速度较慢,因此这可能会使您的测试偏向于更多的集成测试而不是单元测试(但这种区别本身就是一个晚上的价值或争论)。
如果您想对整个 API 进行端到端测试,可以查看 SuperTest NPM package。
(编辑)添加了使用 sinon
的小示例
const AWS = require('aws-sdk');
const sinon = require('sinon');
const ddb = new AWS.DynamoDB.DocumentClient();
const getStub = sinon.stub(AWS.DynamoDB.DocumentClient.prototype, "get");
getStub.callsFake((params, cb) => {
cb(null, {result: []});
});
ddb.get({foo: 'bar'}, (err, val) => {
console.log(val); // => { "result": [] }
})
我是 Jest 和单元测试的新手,我在 AWS.Express 的无服务器(Lambda)上部署了一个 express API api 使用 dynamodb 进行 crud 操作
注意:- 我的 api 是基于 express 的,而不仅仅是普通节点,因为在 jest website 上他们告诉了普通 nodejs
我能够对不使用的方法进行单元测试 dynamodb.However 对于使用 dynamodb 的方法,它失败了,据我所知,这与 dynamodb 是远程的有关,因为 app.js 中的代码对应于使用 lambda 在 aws 上托管的 dyanmo 数据库。
我该怎么做?
注意:- 我的 api 是基于 express 而不是简单的节点
const isUrl = require('is-url');
const AWS = require('aws-sdk');
const { nanoid } = require('nanoid/async');
const express = require('express');
const router = express.Router();
const dynamoDb = new AWS.DynamoDB.DocumentClient();
// URL from users
router.post('/', async (req, res, next) => {
// urlId contains converted short url characters generated by nanoid
const urlId = await nanoid(8);
const { longUrl } = req.body;
// Veryfying url Format using isUrl, this return a boolean
const checkUrl = isUrl(longUrl);
if (checkUrl === false) {
res.status(400).json({ error: 'Invalid URL, please try again!!!' });
}
const originalUrl = longUrl;
const userType = 'anonymous'; // user type for anonymous users
const tableName = 'xxxxxxxxxxxxx'; // table name for storing url's
const anonymousUrlCheckParams = {
TableName: tableName,
Key: {
userId: userType,
originalUrl,
},
};
dynamoDb.get(anonymousUrlCheckParams, (err, data) => {
const paramsForTransaction = {
TransactItems: [
{
Put: {
TableName: tableName,
Item: {
userId: userType,
originalUrl,
convertedUrl: `https://xxxxxxxxxxxxxxxx/${urlId}`,
},
},
},
{
Put: {
TableName: tableName,
Item: {
userId: urlId,
originalUrl,
},
ConditionExpression: 'attribute_not_exists(userId)',
},
},
],
};
if (err) {
console.log(err);
res
.status(500)
.json({ error: 'Unknown Server Error, Please Trimify Again!' });
} else if (Object.keys(data).length === 0 && data.constructor === Object) {
dynamoDb.transactWrite(paramsForTransaction, async (error) => {
if (error) {
// err means converted value as userId is repeated twice.
console.log(error);
res
.status(500)
.json({ error: 'Unknown Server Error, Please trimify again. ' });
} else {
res.status(201).json({
convertedUrl: `https://xxxxxxxxxxxx/${urlId}`,
});
}
});
} else {
res.status(201).json({
convertedUrl: data.Item.convertedUrl,
});
}
});
});
module.exports = router;
我的test.js
const request = require('supertest');
const app = require('../app');
test('Should convert url from anonymous user ', async () => {
await request(app)
.post('/anon-ops/convert')
.send({
longUrl: 'https://google.com',
})
.expect(201);
});
首先,如果您想进行单元测试。您是否使用 express js 并不重要,因此,jest 网站上的示例和信息非常有效,可以帮助您上路。
进行单元测试的难易程度主要取决于您构建代码的方式。例如,您可以将所有 express js 特定代码保存在单独的文件中,然后仅在单元测试期间实例化包含实际业务逻辑(有些人可能称为服务层)的文件。这至少是您可以让自己更轻松的一种方式。使用函数式方法还可以让您的代码更易于测试,或者至少可以使用依赖注入,因此您可以在测试期间交换依赖项,以便单独测试某些功能。
谈到 DynamoDB,您有两个选择。模拟或 运行 本地版本。
您可以使用 jest mocks or using a mocking library such as sinon 模拟您正在调用的特定函数。选择哪个主要是个人喜好。
第二个选项是运行一个local version of DynamoDB in a docker container。这也有验证您对 DynamoDB 服务的实际调用的好处(您可以通过验证模拟来完成,但在验证中很容易出错),但是,设置起来更麻烦,您的测试将是速度较慢,因此这可能会使您的测试偏向于更多的集成测试而不是单元测试(但这种区别本身就是一个晚上的价值或争论)。
如果您想对整个 API 进行端到端测试,可以查看 SuperTest NPM package。
(编辑)添加了使用 sinon
的小示例const AWS = require('aws-sdk');
const sinon = require('sinon');
const ddb = new AWS.DynamoDB.DocumentClient();
const getStub = sinon.stub(AWS.DynamoDB.DocumentClient.prototype, "get");
getStub.callsFake((params, cb) => {
cb(null, {result: []});
});
ddb.get({foo: 'bar'}, (err, val) => {
console.log(val); // => { "result": [] }
})