【问题标题】:How to pass in the result of an async call to shared functions in Jest如何将异步调用的结果传递给 Jest 中的共享函数
【发布时间】:2022-01-13 20:55:03
【问题描述】:

问题

我正在测试 API 端点,并且对每个端点都有一些相同的测试。我不想复制和粘贴,而是想在可重用的功能中分享它。我还希望为每个函数将一条语句打印到控制台(通过test),所以我不想结合逻辑。

代码

这是应该共享的功能:

export function basicTests(res) {
  test("should respond with a 200 status code", () => {
    expect(res.statusCode).toBe(200);
  });

  test("should specify json in the content type header", () => {
    expect(res.headers["content-type"]).toEqual(expect.stringContaining("json"));
  });

  test("should return an ok property", () => {
    expect(res.body.ok).toBeDefined();
  });

  test("should return a description property", () => {
    expect(res.body.description).toBeDefined();
  });
}

这是我在另一个文件中调用测试的方式:

let res = {}
beforeAll(async () => {
  const response = await request(app)
    .get("/some/api/check")
    .send();

  res = { ...response };
});

describe("GET /some/api/route", () => {
  basicTests(res);
  // ... more tests
});

什么不起作用

目前当我传入res 时,它始终是一个空对象。因此,即使 beforeAll 在测试之前运行,变量似乎也更早通过,因此在 Promise 解决时不会更新。

我该如何解决这个问题?

【问题讨论】:

    标签: javascript node.js ecmascript-6 jestjs supertest


    【解决方案1】:

    测试用例是同步定义的。这意味着当 basicTests 函数执行时,res 是空对象 {}

    beforeAll(fn, timeout):

    在此文件中的任何测试运行之前运行一个函数。如果函数返回一个 Promise 或者是一个生成器,Jest 会在运行测试之前等待该 Promise 解决。

    这意味着在beforeAll 中传递的函数将在测试用例函数执行之前运行。由于该函数返回一个承诺,因此 jest 等待该承诺。

    主要区别在于声明和运行时。

    一种解决方案是将beforeAll 的东西放入basicTests 函数中。例如

    basicTests.ts:

    import request from 'supertest';
    
    export function basicTests(app, route) {
      describe('basic test suites', () => {
        let res;
        beforeAll(async () => {
          const response = await request(app).get(route);
          res = { ...response };
        });
        test('should respond with a 200 status code', () => {
          expect(res.statusCode).toBe(200);
        });
    
        test('should specify json in the content type header', () => {
          expect(res.headers['content-type']).toEqual(expect.stringContaining('json'));
        });
    
        test('should return an ok property', () => {
          expect(res.body.ok).toBeDefined();
        });
    
        test('should return a description property', () => {
          expect(res.body.description).toBeDefined();
        });
      });
    }
    

    app.ts:

    import express from 'express';
    
    const app = express();
    
    app.get('/some/api/check', (req, res) => {
      res.json({ ok: true, description: null, data: 'a' });
    });
    
    export { app };
    

    app.test.ts:

    import { basicTests } from './basicTests';
    import request from 'supertest';
    import { app } from './app';
    
    describe('GET /some/api/route', () => {
      basicTests(app, '/some/api/check');
      let res;
      beforeAll(async () => {
        const response = await request(app).get('/some/api/check');
        res = { ...response };
      });
      test('should return data', () => {
        expect(res.body.data).toBe('a');
      });
    });
    

    测试结果:

     PASS  stackoverflow/70702998/app.test.ts (8.972 s)
      GET /some/api/route
        ✓ should return data
        basic test suites
          ✓ should respond with a 200 status code (2 ms)
          ✓ should specify json in the content type header
          ✓ should return an ok property
          ✓ should return a description property
    
    Test Suites: 1 passed, 1 total
    Tests:       5 passed, 5 total
    Snapshots:   0 total
    Time:        9.042 s
    

    【讨论】:

    • 像魅力一样工作。非常感谢。
    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2020-06-13
    • 2015-10-12
    相关资源
    最近更新 更多