You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jest中验证GET接口返回数组为Flight类型?

问题

我正在开发一个API,调用GET请求/api/flights/会返回一组Flight对象,所有Flight对象属性结构一致。希望在Jest测试中验证响应体中的flights列表是否为Flight类型数组,求实现方法。

测试代码如下:

test('Show flight', async () => {
    const response = await supertest(app.express)
        .get('/api/flights/')
        .expect(200);

    //Here i want to check if response.body equals an array of Flight type
});

响应体示例:

{
"flights": [
    {
        "_id": "6300bee627fff32a054f5355",
        "name": "Kiyv Madrid",
        "from": "Kiyv",
        "destination": "Madrid",
        "transplants": [],
        "departureDate": "20.08.2022-09:30",
        "arrivalDate": "21.08.2022-01:00",
        "seatsCount": 150,
        "createdAt": "2022-08-20T11:00:54.844Z",
        "updatedAt": "2022-08-20T11:00:54.844Z",
        "__v": 0
    },
    {
        "_id": "6300bf0127fff32a054f5358",
        "name": "Kyiv Barcelona",
        "from": "Kyiv",
        "destination": "Barcelona",
        "transplants": [],
        "departureDate": "20.08.2022-09:30",
        "arrivalDate": "21.08.2022-01:00",
        "seatsCount": 150,
        "createdAt": "2022-08-20T11:01:21.853Z",
        "updatedAt": "2022-08-20T12:45:42.596Z",
        "__v": 0
    },
    {
        "_id": "6300bf2a1df953f67f0e79b5",
        "name": "Kyiv Madrid",
        "from": "Kyiv",
        "destination": "Madrid",
        "transplants": [],
        "departureDate": "20.08.2022-09:30",
        "arrivalDate": "21.08.2022-01:00",
        "seatsCount": 150,
        "createdAt": "2022-08-20T11:02:02.154Z",
        "updatedAt": "2022-08-20T11:02:02.154Z",
        "__v": 0
    }
  ]
}

Flight类型定义(flight.test.interface.ts):

interface Flight {
    _id: string;
    name: string;
    from: string;
    destination: string;
    transplants: string;
    departureDate: string;
    arrivalDate: string;
    seatsCount: number;
    __v: number;
}

export default Flight;
解决方案

首先明确:TypeScript的类型仅存在于编译阶段,运行时会被完全擦除,所以Jest无法直接验证response.body.flights是否为Flight类型数组,必须通过运行时结构校验实现。下面提供几种实用方案:

方法1:手写类型守卫函数校验

自己实现一个类型守卫函数,判断单个对象是否符合Flight结构,再遍历数组逐个验证:

import Flight from './flight.test.interface';

// 类型守卫:运行时判断对象是否符合Flight结构
function isFlight(obj: unknown): obj is Flight {
    if (typeof obj !== 'object' || obj === null) return false;
    const f = obj as Flight;
    // 注意:你的响应中transplants是数组,但类型定义写的是string,建议将类型修正为string[]
    return (
        typeof f._id === 'string' &&
        typeof f.name === 'string' &&
        typeof f.from === 'string' &&
        typeof f.destination === 'string' &&
        Array.isArray(f.transplants) &&
        typeof f.departureDate === 'string' &&
        typeof f.arrivalDate === 'string' &&
        typeof f.seatsCount === 'number' &&
        typeof f.__v === 'number'
    );
}

test('Show flight', async () => {
    const response = await supertest(app.express)
        .get('/api/flights/')
        .expect(200);

    // 先确认返回结构包含flights数组
    expect(response.body).toHaveProperty('flights');
    expect(Array.isArray(response.body.flights)).toBe(true);

    // 逐个验证数组元素是否符合Flight结构
    response.body.flights.forEach(flight => {
        expect(isFlight(flight)).toBe(true);
        // 可添加细节校验,比如座位数必须为正整数
        expect(flight.seatsCount).toBeGreaterThan(0);
    });
});

方法2:用jest-extended简化断言

借助jest-extended库提供的扩展断言,减少重复代码:

  1. 安装依赖:
npm install jest-extended --save-dev
  1. 在测试文件顶部导入扩展:
import 'jest-extended';
  1. 结合类型守卫使用:
test('Show flight', async () => {
    const response = await supertest(app.express)
        .get('/api/flights/')
        .expect(200);

    expect(response.body.flights).toBeArray();
    expect(response.body.flights.every(isFlight)).toBe(true);
});

方法3:JSON Schema校验(更严谨)

如果需要更严格的结构校验(比如字段格式、数值范围),可以用JSON Schema配合jest-json-schema:

  1. 安装依赖:
npm install jest-json-schema --save-dev
  1. 定义Flight的JSON Schema:
const flightSchema = {
    type: 'object',
    required: ['_id', 'name', 'from', 'destination', 'transplants', 'departureDate', 'arrivalDate', 'seatsCount', '__v'],
    properties: {
        _id: { type: 'string' },
        name: { type: 'string' },
        from: { type: 'string' },
        destination: { type: 'string' },
        transplants: { type: 'array', items: { type: 'string' } }, // 匹配响应中的数组类型
        departureDate: { type: 'string' },
        arrivalDate: { type: 'string' },
        seatsCount: { type: 'integer', minimum: 1 }, // 限制座位数为正整数
        __v: { type: 'integer' }
    },
    additionalProperties: true // 允许响应包含额外字段(如createdAt、updatedAt)
};
  1. 在测试中使用:
import { matchers } from 'jest-json-schema';

// 扩展Jest的断言方法
expect.extend(matchers);

test('Show flight', async () => {
    const response = await supertest(app.express)
        .get('/api/flights/')
        .expect(200);

    expect(response.body.flights).toBeArrayOfObjects();
    response.body.flights.forEach(flight => {
        expect(flight).toMatchSchema(flightSchema);
    });
});

重要提醒

  • 你的Flight类型定义中transplants为string类型,但响应体中实际是数组,二者不一致,建议将类型修正为string[],避免编译时类型错误。
  • 如果响应体包含类型定义中没有的字段(如createdAt、updatedAt),校验时需允许这些额外字段存在,否则会校验失败。

内容的提问来源于stack exchange,提问作者Solyridz3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:36:28