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

如何借助Mock库基于Schema生成异常数据测试Web API错误场景?

刚好我之前做过类似的API错误场景测试,给你梳理一下可行的方案和规范流程~

推荐的Mock数据生成工具

首先给你推荐几个能同时生成正常/异常Mock数据的工具,适配不同技术栈:

  • Faker.js + 自定义封装:Faker本身擅长生成符合真实场景的正常数据,你可以封装一层工具函数,针对指定字段注入错误逻辑(比如把邮箱改成invalid-email、姓名加数字),灵活性很高。
  • json-schema-faker + 错误修改器:它能直接基于JSON Schema生成合规的正常数据,搭配自定义函数可以快速修改指定字段,生成不符合规则的异常数据,适合用JSON Schema做校验的场景。
  • Mongoose反向Mock工具:如果你的服务用Mongoose模型,可以利用模型的验证规则反向推导异常数据——比如针对email字段生成不含@的字符串,针对phone生成带非数字的内容。
  • Mockaroo:支持可视化定义Schema和异常规则(比如强制生成格式错误的邮箱),也提供API可以程序化调用生成数据,适合快速批量生成测试用例。
API错误场景测试的流程规范

这类测试的核心是覆盖所有字段的验证规则,并且和API返回的错误码/信息一一对应,推荐按以下流程来:

  1. 梳理所有字段的验证规则:先把用户服务每个字段的规则列全,比如:
    • name:非空、长度2-50、仅允许字母和空格
    • email:符合RFC格式、非空
    • phone:10位数字、非空
  2. 为每个规则生成独立测试用例:每条验证规则对应一个错误场景,比如name为空、name含数字、邮箱无@符号等,避免用一个测试覆盖多个错误。
  3. 关联错误码与错误信息:测试时不仅要断言请求被拒绝,还要验证返回的错误码(比如EMAIL_INVALID)和错误描述完全匹配预期,确保API的错误反馈符合设计。
  4. 模块化生成异常数据:写一个通用工具函数,接收正常Mock数据和错误配置(比如{ field: 'email', errorType: 'no-at-sign' }),返回对应的异常数据,减少重复代码。
  5. 按逻辑分组测试用例:把测试用例按正常场景、字段错误场景分组,让代码结构更清晰,比如单独用一个describe块包裹所有email相关的错误测试。
代码示例(基于json-schema-faker)

下面是结合你的代码改造的示例,用json-schema-faker生成数据,搭配自定义工具生成异常用例:

首先安装依赖:

npm install json-schema-faker faker should --save-dev

然后写Mock数据生成工具:

const jsf = require('json-schema-faker');
const faker = require('faker');

// 你的用户JSON Schema
const userSchema = {
  type: 'object',
  properties: {
    name: {
      type: 'string',
      minLength: 2,
      maxLength: 50,
      pattern: '^[A-Za-z\\s]+$'
    },
    email: {
      type: 'string',
      format: 'email'
    },
    phone: {
      type: 'string',
      pattern: '^\\d{10}$'
    }
  },
  required: ['name', 'email', 'phone']
};

// 生成正常用户数据
const generateValidUser = () => jsf.generate(userSchema);

// 生成指定字段的异常数据
const generateInvalidUser = (field, errorType) => {
  const validUser = generateValidUser();
  switch (field) {
    case 'name':
      if (errorType === 'too-short') validUser.name = 'A';
      else if (errorType === 'has-numbers') validUser.name = `${faker.name.firstName()}123`;
      else if (errorType === 'empty') validUser.name = '';
      break;
    case 'email':
      if (errorType === 'no-at') validUser.email = 'invalid-email.com';
      else if (errorType === 'invalid-domain') validUser.email = 'user@.com';
      break;
    case 'phone':
      if (errorType === 'non-numeric') validUser.phone = '123-abc-4567';
      else if (errorType === 'wrong-length') validUser.phone = '12345';
      break;
    default:
      throw new Error(`Unsupported error type for field: ${field}`);
  }
  return validUser;
};

module.exports = { generateValidUser, generateInvalidUser };

最后是测试代码:

const app = require('./myapp');
const { generateValidUser, generateInvalidUser } = require('./user-mock-generator');
const should = require('should');

describe('users service', () => {
  // 正常场景测试
  it('create method - should create user with valid data', () => {
    const validUser = generateValidUser();
    return app.service('users')
      .create(validUser)
      .should.eventually.have.property('_id');
  });

  // Email错误场景分组
  describe('create method - email validation errors', () => {
    it('should reject when email has no @ sign', () => {
      const invalidUser = generateInvalidUser('email', 'no-at');
      return app.service('users')
        .create(invalidUser)
        .should.be.rejectedWith(Error, 'Invalid email format')
        .and.have.property('code', 'EMAIL_INVALID');
    });

    it('should reject when email has invalid domain', () => {
      const invalidUser = generateInvalidUser('email', 'invalid-domain');
      return app.service('users')
        .create(invalidUser)
        .should.be.rejectedWith(Error, 'Invalid email domain')
        .and.have.property('code', 'EMAIL_DOMAIN_INVALID');
    });
  });

  // Name错误场景分组
  describe('create method - name validation errors', () => {
    it('should reject when name is too short', () => {
      const invalidUser = generateInvalidUser('name', 'too-short');
      return app.service('users')
        .create(invalidUser)
        .should.be.rejectedWith(Error, 'Name must be at least 2 characters')
        .and.have.property('code', 'NAME_TOO_SHORT');
    });
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:10:06