如何将异步调用的结果传递给Jest中的共享函数



问题

我正在测试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解析时不会更新。

我该怎么解决这个问题?

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

beforeAll(fn, timeout):

在运行此文件中的任何测试之前运行函数。如果函数返回promise或是生成器,Jest将在运行测试之前等待该promise的解析。

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

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

一种解决方案是将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

最新更新