【问题标题】:How to print the request and response when a test fails in Jest?在 Jest 中测试失败时如何打印请求和响应?
【发布时间】:2019-08-01 10:00:25
【问题描述】:

我正在使用 Supertest 和 Jest 来测试 Node.js API。

样本测试具有以下格式

it('Read a note for a user', (done) => {
      request(graphqlURL)
        .post('/graphql')
        .set(baseHeaders())
        .send({
          query: graphQLQuery
        })
        .end((err, res) => {
          expect(res.status).toBe(200);          
          done();
        })

    });

当前当期望失败时,会记录以下内容

expect(received).toBe(expected) // Object.is equality

    Expected: 200
    Received: 404

我还想在失败的测试旁边记录请求和响应,以便在调试时获得更多上下文。

有没有办法也打印那些,仅用于失败的测试?

【问题讨论】:

    标签: node.js jestjs supertest


    【解决方案1】:

    如果您为正文添加额外的期望,如果它与期望的不匹配,它将被记录下来。在状态码期望之前有这个期望会导致你想要的效果。

    【讨论】:

      【解决方案2】:

      expect 通过在期望失败时抛出 Error 来工作。

      Errormessage 属性是打印在测试报告中的内容。

      我想如果您想使用 现有 期望并且只是想用附加数据增加失败消息,您可以捕获 Error,将附加数据附加到 message 属性,然后像这样再次抛出Error

      it('Read a note for a user', (done) => {
        request(graphqlURL)
          .post('/graphql')
          .set(baseHeaders())
          .send({
            query: graphQLQuery
          })
          .end((err, res) => {
            try {
              expect(res.status).toBe(200);
            } catch (err) {
              // --- add additional data to the error message here ---
              err.message = `${err.message}\n\nfailing query: ${graphQLQuery}`;
              throw err;  // throw the error so test fails as expected
            }
            done();
          })
      });
      

      【讨论】:

      • 这在很大程度上解决了我的问题。不过有一个小问题。 console.log 语句与测试报告分开打印。测试失败的报告与该测试的相应console.log 语句分开打印。这使得将请求响应与相应的失败测试相匹配变得乏味。关于如何减轻这种情况的任何想法?
      • @dsinecos 我更新了我的答案,将附加数据添加到 Errormessage 属性中,以便打印在测试报告中
      • 非常感谢@brian-lives-outdoors,这解决了我的问题
      【解决方案3】:

      您可以创建一个custom matcher,在期望失败时记录响应:

      expect.extend({
        statusCode(expected, response) {
          const { status } = response
          const pass = expected === status
      
          if (pass) {
            return {
              message: () =>
                `expected ${status} to be ${expected}`,
              pass: true
            }
          } else {
            return {
              message: () =>
                `expected ${status} to be ${expected}. Response: ${response}`,
              pass: false
            }
          }
        }
      })
      

      然后在您的测试中,使用自定义匹配器而不是典型的expect

      it('Read a note for a user', (done) => {
        request(graphqlURL)
          .post('/graphql')
          .set(baseHeaders())
          .send({
            query: graphQLQuery
          })
          .end((err, res) => {
            expect.statusCode(200, res)     
            done()
          })
      })
      

      很遗憾,there isn't really a way to access the HTTP request using supertest。但是您可以在自定义匹配器的签名中添加有关您确实拥有的请求的任意信息。

      【讨论】:

      • 谢谢,这是我考虑过的方法之一。我可以看到的缺点是我必须为不同类型的比较编写自定义匹配器。您共享了一个状态码匹配器。在测试中,我还将比较响应体的不同部分。据我了解,我必须为每个人编写一个自定义匹配器?这有意义吗?
      • 您可以编写一个类似的带有日志记录的自定义匹配器,将超测试响应与另一个对象进行比较,并验证该对象是响应的子集。所以类似于expect.toMatchObject 的东西,但是带有修改后的消息。
      • 我接受了另一个答案。我担心的是,这要么会限制我可以在响应中使用的匹配器数量,要么最终会重写 Jest 提供的匹配器。感谢您的帮助:)
      【解决方案4】:

      您可以像这样打印响应:

      it('Read a note for a user', (done) => {
        request(graphqlURL)
          .post('/graphql')
          .set(baseHeaders())
          .send({
            query: graphQLQuery
          })
          .end((err, res) => {
            if(!expect(res.status).toBe(200)) console.log('res',res) // print response
            expect(res.status).toBe(200);          
            done();
          })
      
        });
      

      【讨论】:

      • 我只想在期望失败时打印响应。在这种情况下,无论测试通过还是失败,都会打印响应
      • 您现在可以查看
      • 如果期望失败,这仍然不会打印响应。仅当err 为真值时才会打印
      • 我正在寻找另一种答案中建议的更通用的方法。感谢您的帮助:)
      猜你喜欢
      • 2014-10-10
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      相关资源
      最近更新 更多