问题
我正在测试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