You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Cypress中异步查询PostgreSQL数据库的测试方法及导出查询函数返回空数据问题排查

在Cypress中实现PostgreSQL异步查询及函数返回空的解决方案

首先,你的数据库查询函数返回空的问题很典型——异步逻辑处理不当,导致函数在查询结果返回前就“提前结束”了。咱们先把这个问题解决,再讲如何在Cypress里正确集成PostgreSQL查询。

一、修复你的数据库查询函数

问题根源

你写的new Promise()构造函数里,既没有调用resolve()把查询结果传递出去,也没有正确处理database.raw()的返回值。而且database.select(database.raw(...))的写法是多余的,直接用database.raw(query)就能执行原生SQL查询了。

修正后的函数(推荐写法)

因为database.raw()本身就返回一个Promise,所以咱们不需要额外再包裹一层Promise,直接返回它就行:

export function queryDb(query) {
  return database.raw(query)
    .then(data => {
      // 注意:不同的数据库库(比如knex、pg-promise)返回的数据结构不同,这里假设是data.rows
      return data.rows; 
    })
    .catch(err => {
      console.error('数据库查询出错:', err.message);
      // 抛出错误让外部测试可以捕获并处理
      throw err;
    });
}

如果你一定要手动包裹Promise(不推荐,有点画蛇添足),那必须在回调里调用resolve和reject:

export function queryDb(query) {
  return new Promise((resolve, reject) => {
    database.raw(query)
      .then(data => {
        resolve(data.rows); // 关键:把结果传递给Promise的调用者
      })
      .catch(err => {
        console.error('数据库查询出错:', err.message);
        reject(err); // 传递错误信息
      });
  });
}

二、在Cypress中正确使用异步数据库查询

Cypress的测试逻辑是基于命令队列的,处理异步操作得跟着它的规则来,这里给你三种常用的实现方式:

方式1:直接在测试中调用函数(用.then处理结果)

因为queryDb返回Promise,咱们可以用cy.wrap()把它纳入Cypress的命令链,这样就能保证测试等待查询完成后再继续:

import { queryDb } from './path/to/your/function';

describe('数据库查询测试', () => {
  it('验证用户数据是否正确', () => {
    cy.wrap(queryDb('SELECT * FROM users WHERE id = 1'))
      .then(userData => {
        // 在这里写断言逻辑
        expect(userData).to.have.length(1);
        expect(userData[0].username).to.equal('test_user');
      });
  });
});

方式2:自定义Cypress命令(复用性更强)

如果多个测试用例都要用到数据库查询,建议把它注册成Cypress自定义命令,方便调用:

  1. 在cypress/support/commands.js里注册命令:
import { queryDb } from '../path/to/your/function';

Cypress.Commands.add('queryDb', (query) => {
  return cy.wrap(queryDb(query));
});
  1. 在测试文件中直接使用:
describe('商品数据测试', () => {
  it('查询价格大于100的商品', () => {
    cy.queryDb('SELECT * FROM products WHERE price > 100')
      .then(products => {
        expect(products).to.not.be.empty;
      });
  });
});

方式3:使用Cypress Task(适合复杂后台操作)

如果不想把数据库连接逻辑暴露在前端测试代码里,可以把查询逻辑放在Cypress的插件层(Node.js环境),通过cy.task调用:

  1. 在cypress.config.js(Cypress 10+版本)中配置task:
const { defineConfig } = require('cypress');
// 导入你的数据库连接,比如用knex
const knex = require('knex')({
  client: 'pg',
  connection: {
    host: '你的数据库地址',
    user: '数据库用户名',
    password: '数据库密码',
    database: '数据库名称'
  }
});

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        queryDb: (query) => {
          return knex.raw(query)
            .then(data => data.rows)
            .catch(err => {
              console.error('查询出错:', err);
              throw err;
            });
        }
      });
    },
  },
});
  1. 在测试文件中调用task:
describe('订单统计测试', () => {
  it('验证订单总数不为0', () => {
    cy.task('queryDb', 'SELECT COUNT(*) FROM orders')
      .then(countResult => {
        expect(countResult[0].count).to.be.greaterThan(0);
      });
  });
});

三、几个关键注意事项

  • 确保你的数据库连接配置正确,而且Cypress运行环境能访问到数据库(本地测试要启动数据库,CI环境要配置好网络权限)。
  • 不同的数据库工具库返回的数据结构不一样,比如knex返回的data.rows是查询结果数组,而pg-promise可能直接返回数组,要根据你用的库调整返回值。
  • 在Cypress里尽量别直接用async/await包裹测试代码,因为Cypress的命令队列和普通异步函数的执行顺序不同,容易出时序问题;如果要用,得结合cy.wrap或者在task里使用。

内容的提问来源于stack exchange,提问作者Thiago Mendes de Souza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:27:42