前后端接口参数详解与 Mock 配置指南【大模型总结】

发布于:2025-04-08 ⋅ 阅读:(13) ⋅ 点赞:(0)

前后端接口参数详解与 Mock 配置指南


一、前端请求参数类型及 Mock 处理

1.1 URL 路径参数 (Path Parameters)

场景示例

GET /api/users/{userId}/orders/{orderId}

Mock.js 处理

Mock.mock(/\/api\/users\/(\d+)\/orders\/(\d+)/, 'get', (options) => {
  const userId = options.url.match(/\/users\/(\d+)/)[1];
  const orderId = options.url.match(/\/orders\/(\d+)/)[1];
  return {
    userId,
    orderId,
    totalPrice: Mock.Random.float(100, 1000, 2)
  };
});

MSW 动态匹配

rest.get('/api/users/:userId/orders/:orderId', (req, res, ctx) => {
  const { userId, orderId } = req.params;
  return res(
    ctx.json({ 
      userId: Number(userId),
      orderId: Number(orderId),
      status: 'processed'
    })
  );
});

1.2 查询参数 (Query Parameters)

场景示例

GET /api/products?category=electronics&page=2&sort=price_desc

Mock.js 响应逻辑

Mock.mock(/\/api\/products/, 'get', (options) => {
  const query = new URLSearchParams(options.url.split('?')[1]);
  return {
    page: query.get('page') || 1,
    data: Mock.mock({
      'list|10': [{
        id: '@id',
        name: '@ctitle',
        'price|100-5000': 1,
        category: query.get('category') || 'all'
      }]
    })
  };
});

WireMock 精确匹配

stubFor(get(urlPathEqualTo("/api/products"))
    .withQueryParam("category", equalTo("electronics"))
    .withQueryParam("page", equalTo("2"))
    .willReturn(aResponse()
        .withHeader("Content-Type", "application/json")
        .withBodyFile("products/electronics_page2.json")));

1.3 请求体参数 (Body Parameters)

场景示例

POST /api/login
Content-Type: application/json

{
  "username": "admin",
  "password": "P@ssw0rd"
}

MSW 处理逻辑

rest.post('/api/login', async (req, res, ctx) => {
  const { username, password } = await req.json();
  if (password.length < 8) {
    return res(
      ctx.status(400),
      ctx.json({ error: "密码长度不足8位" })
    );
  }
  return res(
    ctx.json({
      token: Buffer.from(username).toString('base64'),
      expiresIn: 3600
    })
  );
});

WireMock JSON 匹配

stubFor(post(urlEqualTo("/api/login"))
    .withRequestBody(matchingJsonPath("$.username"))
    .withRequestBody(matchingJsonPath("$.password"))
    .willReturn(aResponse()
        .withStatus(200)
        .withBody("{\"token\": \"{{randomValue length=32 type='ALPHANUMERIC'}}\"}")));

二、后端接口参数 Mock 策略

2.1 Spring Boot MockMvc 参数验证

路径参数测试

@Test
void testGetUserById() throws Exception {
  mockMvc.perform(get("/users/{id}", 123))
         .andExpect(status().isOk())
         .andExpect(jsonPath("$.id").value(123));
}

请求体验证测试

@Test
void testCreateProduct() throws Exception {
  String jsonBody = "{ \"name\":\"iPhone\", \"price\":6999 }";
  
  mockMvc.perform(post("/products")
         .contentType(MediaType.APPLICATION_JSON)
         .content(jsonBody))
         .andExpect(status().isCreated())
         .andExpect(jsonPath("$.sku").exists());
}

2.2 Mockito 参数匹配技巧

基础参数匹配

// 任意字符串参数
when(userDao.findByUsername(anyString()))
   .thenReturn(new User("default"));

// 特定类型匹配
when(orderService.calculateTotal(any(Order.class)))
   .thenReturn(100.0);

自定义参数验证

ArgumentCaptor<Product> productCaptor = ArgumentCaptor.forClass(Product.class);
verify(productRepository).save(productCaptor.capture());

Product savedProduct = productCaptor.getValue();
assertThat(savedProduct.getPrice()).isBetween(100, 10000);

三、高级参数处理场景

3.1 文件上传参数

Multipart 请求 Mock

// Spring Boot 测试示例
@Test
void testUploadAvatar() throws Exception {
  MockMultipartFile file = new MockMultipartFile(
      "file", 
      "avatar.png", 
      "image/png", 
      "<<png data>>".getBytes()
  );

  mockMvc.perform(multipart("/upload")
         .file(file)
         .param("userId", "123"))
         .andExpect(status().isOk());
}

3.2 OAuth2 认证头处理

WireMock 带鉴权头的模拟

stubFor(get(urlPathEqualTo("/api/protected"))
    .withHeader("Authorization", containing("Bearer "))
    .willReturn(aResponse()
        .withStatus(200)
        .withBody("{\"secretData\":\"TOP_SECRET\"}"));

Mockito 模拟安全上下文

@Mock
private JwtDecoder jwtDecoder;

@Test
void testSecuredEndpoint() {
  Jwt jwt = Jwt.withTokenValue("token")
              .header("alg", "HS256")
              .claim("sub", "user123")
              .build();
  
  when(jwtDecoder.decode(anyString())).thenReturn(jwt);
  
  // 执行需要认证的测试逻辑
}

四、参数异常模拟

4.1 无效参数响应

Mock.js 模拟参数错误

Mock.mock(/\/api\/search/, 'get', (options) => {
  const keyword = options.url.split('keyword=')[1];
  if (!keyword || keyword.length < 2) {
    return { 
      code: 400, 
      error: "关键词长度需大于2个字符" 
    };
  }
  // 正常返回逻辑...
});

4.2 类型转换错误

WireMock 错误响应模板

stubFor(get(urlPathEqualTo("/api/items"))
    .withQueryParam("page", matching("[0-9]+"))
    .willReturn(aResponse()
        .withStatus(400)
        .withBody("{\"error\":\"页码必须是数字\"}")));

五、参数调试技巧

5.1 请求日志记录

WireMock 请求捕获

WireMock.startRecording("http://real-api.com");
List<LoggedRequest> requests = findAll(getRequestedFor(urlPathEqualTo("/api/data")));
System.out.println("捕获请求数量:" + requests.size());

5.2 动态参数生成

Mock.js 智能数据生成

Mock.mock('/api/report', {
  'data|30': [{
    date: "@date('yyyy-MM-dd')",
    'sales|500-2000': 1,
    region: "@region",
    product: "@pick(['手机','电脑','配件'])"
  }]
});

六、参数文档规范建议

6.1 OpenAPI 示例片段

/api/users/{id}:
  get:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
    responses:
      200:
        content:
          application/json:
            schema:
              type: object
              properties:
                id: 
                  type: integer
                name: 
                  type: string


网站公告

今日签到

点亮在社区的每一天
去签到