【问题标题】:Better testing Express routes with test DB in postgreSQL在 postgreSQL 中使用测试数据库更好地测试 Express 路由
【发布时间】:2021-04-29 21:55:14
【问题描述】:

我正在努力提高为我的 Node.js API 编写测试的能力。我的最新项目让我查询端点/api/v1/restaurants,该端点返回包含对象数组的数据。这是控制器中的功能调用:

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)
    }
})
  • 如您所见,我已将 DB 查询抽象为单独的实用程序页面,但我仍将表名“restaurants”作为参数传递。
  • restaurantstest_restaurants 表都是在同一个数据库的本地驱动器上创建和运行的。

当我尝试像这样在测试中进行 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 数据库表 restaurants。我的直接想法是做简单/懒惰的事情并为这样的测试创建一个相同的路线:

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 的人,这似乎更容易设置和拆除测试数据库。谢谢,如果需要更多信息,请告诉我。

【问题讨论】:

    标签: node.js postgresql express jestjs supertest


    【解决方案1】:

    为了更清楚地说明我如何使用@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"
      },
    

    现在我正在使用两个不同的数据库。

    【讨论】:

      【解决方案2】:

      由于您有两个数据库,restaurantstest_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
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 2015-06-13
      相关资源
      最近更新 更多