【问题标题】:Unit Testing Database Queries单元测试数据库查询
【发布时间】:2018-11-30 02:49:25
【问题描述】:

问题:因此,作为单元测试的初学者,我最近遇到的一个问题是处理具有大量数据库使用的类。

使用的技术: Typescript、SinonJS、Node-Postgres 和 Jest

示例:对于给定的函数

public async insertUserDetails() {

  const confirmationCode = this.generateConfirmationCode();

  try {

    await this.db.query({
      text: 'INSERT INTO users (firstname, lastname, email, password, registration_date, confirmation_code) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *',
      values: [this.firstname, this.lastname, this.email, this.password, this.registrationDate, confirmationCode]
    });


  } catch (error) {

    throw error;

  }

}

问题: 合适的单元测试是确保使用正确的 sql 调用 db.query() 函数,如下所示?或者这会被认为是浪费时间和脆弱测试?

test("should format correct sql", async () => {

    //Test Setup
    const user = new User({
        firstname: "John",
        lastname: "doe",
        email: "email@example.com",
        password: "some_password_hash",
        registrationDate: "some_random_date",
    });

    //Mocks
    const queryStub = sinon.stub(user.db, "query");
    const confirmationCode = sinon.stub(user,'generateConfirmationCode').returns("48fsakb8a-cfjdab");

    const sampleQuery = {
        text: 'INSERT INTO users (firstname, lastname, email, password, registration_date, confirmation_code) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *',
        values: [user.firstname, user.lastname, user.email, user.password, user.registrationDate, confirmationCode]
    }

    //Preform
    await user.insertUserDetails();

    //Assert
    sinon.assert.calledWith(queryStub, sampleQuery);


});

或者我应该跳过对这些类型的函数和类的单元测试并建立一个集成测试数据库并通过集成测试来测试这些案例?

这是一个非常简化的示例,因为我没有测试数据库事务,但是测试事务变成了一个更大的蠕虫罐,因为执行了多个查询。

感谢您的帮助!这让我发疯-__-

【问题讨论】:

  • catch (error) { throw error; } 毫无意义。只需删除 try/catch 包装器即可。

标签: javascript node.js unit-testing jestjs sinon


【解决方案1】:

合适的单元测试是确保 db.query() 使用正确的 sql 调用函数,如下所示?

如果您专注于制作 db.query,那么您要做的不是单元测试。然后它变成一个集成测试。在这里,您要测试的单元是insertUserDetails。所以你专注于这个函数的行为。您可以测试的是: 1. 使用正确的参数调用 db.query(希望 this.db 可以模拟) 2. 如果 db.query 抛出异常,则执行 catch 块并抛出异常。

同样,您应该尝试为覆盖query 函数的this.db 类编写单元测试。

因此,一旦您确定两个单元都被正确覆盖,那么这将是一个好的开始。

现在,如果您可以选择一次性编写集成测试,您可以在其中使用某种内存数据库,或者可能是您的真实数据库,然后继续这样做,您不能编写单元测试共。

希望这会有所帮助。

【讨论】:

  • 所以是的,我的数据库连接被注入到我使用的类中,所以模拟它不会有问题,但如果我不确定从输入中生成正确的 sql,我的测试实际上会是什么进行测试?它总是会成功,因为我通过了硬编码的“正确”数据。还是我仍然缺少一些基本的东西?
  • 如果有一种方法可以在另一个函数中提取查询创建部分,然后进行重构并为此编写单元测试。怎么样?
  • 这确实有效!谢谢你。我为失败测试提供了错误数据,为通过测试提供了良好数据,然后在我的集成测试套件中,使用数据库测试系统。谢谢。
猜你喜欢
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多