在 postgreSQL 中使用测试数据库更好地测试 Express 路由
Better testing Express routes with test DB in postgreSQL
我正努力在为我的 Node.js API 编写测试方面做得更好。我的最新项目让我查询一个端点 /api/v1/restaurants
,其中 returns 数据包括一个对象数组。这是控制器内的功能调用:
restaurantRouter.get("/api/v1/restaurants", async (req, res) => {
try {
// const results = await db.query("SELECT * FROM restaurants");
const results = await select("restaurants");
res.status(200).json({
status: "success",
results: results.rows.length,
data: {
restaurants: results.rows
}
})
} catch (err) {
console.log(err)
}
})
- 如您所见,我已将数据库查询抽象为一个单独的实用程序页面,但我仍将 table 名称“restaurants”作为参数传递。
restaurants
和 test_restaurants
table 都已创建,并且 运行 在同一数据库中的本地驱动器上。
当我尝试在我的测试中进行 API 调用时,我的问题就出现了:
test("restaurants are returned as JSON", async () => {
await api
.get("/api/v1/restaurants")
.expect(200)
.expect('Content-Type', /application\/json/)
})
test("all restaurants are returned", async () => {
const response = await api.get("/api/v1/restaurants")
expect(response.body.data).not.toBeEmpty()
expect(response.body.data.restaurants).toBeArrayOfSize(2)
})
他们立即默认为 Dev 数据库 table restaurants
。我的直接想法是只做 easy/lazy 事情并为这样的测试创建一个相同的路径:
restaurantRouter.get("/api/v1/test-restaurants", async (req, res) => {
try {
const results = await select("test_restaurants");
res.status(200).json({
status: "success",
results: results.rows.length,
data: {
restaurants: results.rows
}
})
} catch (err) {
console.log(err)
}
})
是否有更好或更优雅的方法来测试这些?如果没有给出变量参数,也许使用中间件传递默认为 Dev/Prod 数据库的可选变量?
我这几天一直在搜索,所有教程和示例都有人使用 mongoDB,这似乎更容易设置和拆除测试数据库。谢谢,如果需要更多信息,请告诉我。
因为您有两个数据库,restaurants
和 test_restaurants
。
在 package.json
中编辑您的测试命令
"test": "cross-env NODE_ENV=test jest"
.
如果 NODE_ENV
在您的配置中进行测试,则让您的应用使用 test_restaurants
数据库。
if(process.env.NODE_ENV === "test"){
// use test database
}
if(process.env.NODE_ENV !== "test"){
// use production database
}
为了更清楚地说明我如何使用@Odunsi 的回答:
我的 db/index.js
文件:
const { Pool } = require("pg")
const PG_DATABASE = process.env.NODE_ENV === "test"
? process.env.TEST_DATABASE
: process.env.DEV_DATABASE
const pool = new Pool({
user: process.env.PGUSER,
host: process.env.PGHOST,
database: PG_DATABASE,
port: 5432,
password: null
})
pool.on('connect', () => {
console.log(`Connected to the DB: ${process.env.NODE_ENV}`);
});
module.exports = {
query: (text, params) => pool.query(text, params)
}
关键是通过脚本传入 NODE_ENV
(如上面的答案所示),但我不必使用 cross-env
模块。
"scripts": {
"test": "NODE_ENV=test jest --verbose --runInBand",
"dev": "NODE_ENV=development nodemon index.js"
},
现在我使用两个不同的数据库。
我正努力在为我的 Node.js API 编写测试方面做得更好。我的最新项目让我查询一个端点 /api/v1/restaurants
,其中 returns 数据包括一个对象数组。这是控制器内的功能调用:
restaurantRouter.get("/api/v1/restaurants", async (req, res) => {
try {
// const results = await db.query("SELECT * FROM restaurants");
const results = await select("restaurants");
res.status(200).json({
status: "success",
results: results.rows.length,
data: {
restaurants: results.rows
}
})
} catch (err) {
console.log(err)
}
})
- 如您所见,我已将数据库查询抽象为一个单独的实用程序页面,但我仍将 table 名称“restaurants”作为参数传递。
restaurants
和test_restaurants
table 都已创建,并且 运行 在同一数据库中的本地驱动器上。
当我尝试在我的测试中进行 API 调用时,我的问题就出现了:
test("restaurants are returned as JSON", async () => {
await api
.get("/api/v1/restaurants")
.expect(200)
.expect('Content-Type', /application\/json/)
})
test("all restaurants are returned", async () => {
const response = await api.get("/api/v1/restaurants")
expect(response.body.data).not.toBeEmpty()
expect(response.body.data.restaurants).toBeArrayOfSize(2)
})
他们立即默认为 Dev 数据库 table restaurants
。我的直接想法是只做 easy/lazy 事情并为这样的测试创建一个相同的路径:
restaurantRouter.get("/api/v1/test-restaurants", async (req, res) => {
try {
const results = await select("test_restaurants");
res.status(200).json({
status: "success",
results: results.rows.length,
data: {
restaurants: results.rows
}
})
} catch (err) {
console.log(err)
}
})
是否有更好或更优雅的方法来测试这些?如果没有给出变量参数,也许使用中间件传递默认为 Dev/Prod 数据库的可选变量?
我这几天一直在搜索,所有教程和示例都有人使用 mongoDB,这似乎更容易设置和拆除测试数据库。谢谢,如果需要更多信息,请告诉我。
因为您有两个数据库,restaurants
和 test_restaurants
。
在 package.json
中编辑您的测试命令"test": "cross-env NODE_ENV=test jest"
.
如果 NODE_ENV
在您的配置中进行测试,则让您的应用使用 test_restaurants
数据库。
if(process.env.NODE_ENV === "test"){
// use test database
}
if(process.env.NODE_ENV !== "test"){
// use production database
}
为了更清楚地说明我如何使用@Odunsi 的回答:
我的 db/index.js
文件:
const { Pool } = require("pg")
const PG_DATABASE = process.env.NODE_ENV === "test"
? process.env.TEST_DATABASE
: process.env.DEV_DATABASE
const pool = new Pool({
user: process.env.PGUSER,
host: process.env.PGHOST,
database: PG_DATABASE,
port: 5432,
password: null
})
pool.on('connect', () => {
console.log(`Connected to the DB: ${process.env.NODE_ENV}`);
});
module.exports = {
query: (text, params) => pool.query(text, params)
}
关键是通过脚本传入 NODE_ENV
(如上面的答案所示),但我不必使用 cross-env
模块。
"scripts": {
"test": "NODE_ENV=test jest --verbose --runInBand",
"dev": "NODE_ENV=development nodemon index.js"
},
现在我使用两个不同的数据库。