[英]What's the best way to test express.js API
我是使用 JavaScript 進行 API 測試的新手。 我找到了許多測試 REST API 的解決方案,但不確定什么是最好的。 我在后端和測試中使用 express.js 開玩笑。
我已經看到我可以開玩笑地測試,通過模擬函數或者我也可以直接模擬 API。
我有一個存儲對象的 data.js:
let data = [
{
id: 0,
name: "empty shopppinglist",
location: "",
targetDate: "",
priority: "",
isFinished: false,
items: ["vodka"
]
}
]
module.exports = data
然后在后端文件夾中,我有這個來提供端點並讀取/返回文件:
function getData(){
let shoppingLists = data
return shoppingLists
}
module.exports.getData = getData
let shoppingLists = data
app.get('/api/shoppingLists', (req, res) => {
const listsWithoutItems = getData().map(({ items, ...rest }) => rest)
res.status(200).send(listsWithoutItems)
})
我在這里也不確定,如果我可以將 app.get 調用移動到一個函數。
在我的測試中,我想測試 API 的行為,因此如果數據無效,我將收到錯誤 500 等。為此,我已經嘗試過此測試:
describe('Get Endpoint for all Lists', () => {
it('should return 2 lists', async () => {
myapp.getData = jest.fn(() => [
{
"id": 0,
"name": "filled shopping list",
"location": "lidl",
"targetDate": "22.03.1986",
"priority": "1",
"isFinished": false,
"items": ["vanille"
]
}
])
const res = await request(myapp)
.get('/api/shoppingLists')
expect(res.statusCode).toEqual(200)
expect(res.body).toHaveProperty('2')
})
})
不幸的是,我總是從 data.js 獲取原始條目,而不是模擬結果。 通過搜索文檔,我還看到,我可以模擬定義我的 API 的整個 app.js。 但現在我不確定什么是更好的方法。
將getData
模擬為myapp.getData
是不可能的。 module.exports.getData = getData
不能很好地用於測試,因為它允許模擬getData
僅當它在任何地方用作exports.getData()
而不是getData()
,這是不切實際的。
data
需要在它定義的模塊中進行模擬。 然后,每個測試都應該重新導入依賴於它的所有模塊,以便受到模擬的影響。 jest.isolateModules
或jest.resetModules
可以與require
結合使用以提供特定於測試的模塊模擬。
beforeEach(() => {
jest.resetModules();
});
it('should return 2 lists', async () => {
jest.mock('.../data', () => [...]);
const myapp = require('.../app');
const res = await request(myapp)
...
});
我想我已經達到了我想要的設置:
await
,沒有無限深度嵌套的回調在此示例中未顯示,當使用NODE_ENV=test
時,您可能希望通過使用每個測試唯一的臨時內存 SQLite 數據庫運行應用程序來完成任務。 真正的生產服務器會在 PostgreSQL 之類的東西上運行,並且會使用像 sequelize 這樣的 ORM,以便相同的代碼可以在兩者上運行。 或者,您可以設置一次創建數據庫並在每次測試之前截斷所有表。
應用程序.js
#!/usr/bin/env node
const express = require('express')
async function start(port, cb) {
const app = express()
app.get('/', (req, res) => {
res.send(`asdf`)
})
app.get('/qwer', (req, res) => {
res.send(`zxcv`)
})
return new Promise((resolve, reject) => {
const server = app.listen(port, async function() {
try {
cb && await cb(server)
} catch (e) {
reject(e)
this.close()
throw e
}
})
server.on('close', resolve)
})
}
if (require.main === module) {
start(3000, server => {
console.log('Listening on: http://localhost:' + server.address().port)
})
}
module.exports = { start }
測試.js
const assert = require('assert');
const http = require('http')
const app = require('./app')
function testApp(cb) {
return app.start(0, async (server) => {
await cb(server)
server.close()
})
}
// https://stackoverflow.com/questions/6048504/synchronous-request-in-node-js/53338670#53338670
function sendJsonHttp(opts) {
return new Promise((resolve, reject) => {
const body = JSON.stringify(opts.body)
const options = {
hostname: 'localhost',
port: opts.server.address().port,
path: opts.path,
method: opts.method,
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body),
}
}
const req = http.request(options, res => {
res.on('data', data => {
resolve([res, data.toString()])
})
})
req.write(body)
req.end()
})
}
it('test root', () => {
// When an async function is used, Mocha waits for the promise to resolve
// before deciding pass/fail.
return testApp(async (server) => {
let res, data
// First request, normally a POST that changes state.
;[res, data] = await sendJsonHttp({
server,
method: 'GET',
path: '/',
body: {},
})
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(data, 'asdf')
// Second request, normally a GET to check that POST.
;[res, data] = await sendJsonHttp({
server,
method: 'GET',
path: '/',
body: {},
})
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(data, 'asdf')
})
})
it('test /qwer', () => {
return testApp(async (server) => {
let res, data
;[res, data] = await sendJsonHttp({
server,
method: 'GET',
path: '/qwer',
body: {},
})
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(data, 'zxcv')
})
})
包.json
{
"name": "tmp",
"version": "1.0.0",
"dependencies": {
"express": "4.17.1"
},
"devDependencies": {
"mocha": "6.2.2"
},
"scripts": {
"test": "mocha test test.js"
}
}
有了這個,運行:
npm install
./app
根據需要正常運行服務器。 並運行:
npm test
使測試按需要工作。 值得注意的是,如果您將任何斷言破解為錯誤的值,它們將拋出,服務器關閉而不掛起,最后失敗的測試顯示為失敗。
異步 http 請求也在: Node.js 中的同步請求
在 Node.js 14.17.0、Ubuntu 21.10 上測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.