如何将异步调用的结果传递给 Jest 中的共享函数
How to pass in the result of an async call to shared functions in 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)
:
Runs a function before any of the tests in this file run. If the function returns a promise or is a generator, Jest waits for that promise to resolve before running tests.
这意味着在执行测试用例函数之前,beforeAll
中传递的函数将是 运行。由于函数 returns 是一个承诺,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 Whosebug/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
问题
我正在测试 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)
:
Runs a function before any of the tests in this file run. If the function returns a promise or is a generator, Jest waits for that promise to resolve before running tests.
这意味着在执行测试用例函数之前,beforeAll
中传递的函数将是 运行。由于函数 returns 是一个承诺,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 Whosebug/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