十二、Mock Server——用Cypress拦截接口,前端测试不卡壳

Mock Server------用Cypress拦截接口,前端测试不卡壳

做前端测试时,经常遇到"后端接口还没好,前端没法测"的尴尬。这时候,Mock Server就成了救星------它能模拟接口返回,让前端在没有后端的情况下也能正常测试。Cypress不仅能调用接口,还能直接拦截和修改接口返回,自带"Mock功能",这一章咱们就来解锁这个技能。

一、什么是Mock?为什么需要它?

简单说,Mock就是"模拟"------当后端接口还没开发好,或者想测试异常场景(比如接口返回500错误)时,用Mock Server返回预设的结果,让前端测试能继续进行。

比如测试"登录失败"场景,不需要真的输错密码,直接Mock接口返回"密码错误"即可;测试"列表为空",直接让接口返回空数组,不用手动删数据。

二、Cypress自带的Mock:cy.intercept()

Cypress从6.0版本开始,用cy.intercept()命令替代了旧的cy.route(),专门用来拦截HTTP请求。它能做到:

  • 监听指定接口的请求;
  • 模拟接口返回(成功/失败/异常);
  • 修改请求参数或返回数据。

1. 基础用法:拦截接口并返回预设数据

比如拦截"获取商品列表"接口,让它返回我们准备好的Mock数据:

javascript 复制代码
it('Mock商品列表接口', () => {
  // 步骤1:定义Mock数据
  const mockProducts = [
    { id: 1, name: '测试商品1', price: 99 },
    { id: 2, name: '测试商品2', price: 199 }
  ]

  // 步骤2:拦截接口,返回Mock数据
  cy.intercept(
    'GET', // 拦截GET请求
    '/api/products', // 要拦截的接口路径
    mockProducts // 预设的返回数据
  ).as('getProducts') // 给拦截器起个别名,方便后续等待

  // 步骤3:访问页面,触发接口请求
  cy.visit('/products')

  // 步骤4:等待拦截的接口完成
  cy.wait('@getProducts')

  // 步骤5:验证页面展示正确
  cy.get('[data-cy=product-item]').should('have.length', 2)
  cy.get('[data-cy=product-name]').first().should('contain', '测试商品1')
})

这样一来,即使后端的/api/products接口还没好,页面也能展示我们的Mock数据,测试能正常进行。

2. 模拟异常场景:返回错误状态码

测试接口报错时的前端表现(比如显示错误提示),可以让Mock返回500、404等状态码:

javascript 复制代码
it('接口返回500时显示错误提示', () => {
  // 拦截接口,返回500错误
  cy.intercept(
    'GET',
    '/api/products',
    {
      statusCode: 500, // 状态码
      body: { message: '服务器内部错误' } // 错误信息
    }
  ).as('getProducts')

  cy.visit('/products')
  cy.wait('@getProducts')

  // 验证前端显示错误提示
  cy.get('[data-cy=error-message]')
    .should('be.visible')
    .and('contain', '服务器内部错误')
})

3. 动态修改返回数据:部分Mock

有时候不需要完全替换接口返回,只想改部分字段(比如把价格改成0测试折扣场景),可以先让请求走到真实接口,再修改返回数据:

javascript 复制代码
it('修改接口返回的价格字段', () => {
  // 先拦截,让请求正常发送到真实接口
  cy.intercept('GET', '/api/products', (req) => {
    // 等待真实接口返回后,修改数据
    req.continue((res) => {
      // 把所有商品价格改成0
      res.body.forEach(product => {
        product.price = 0
      })
    })
  }).as('getProducts')

  cy.visit('/products')
  cy.wait('@getProducts')

  // 验证价格都变成0
  cy.get('[data-cy=product-price]').each(($el) => {
    cy.wrap($el).should('contain', '0')
  })
})

三、自定义Mock Server:更灵活的场景

如果需要长期维护一套Mock数据,或者多人共享,可以用json-server搭建独立的Mock Server,配合Cypress使用:

1. 搭建本地Mock Server

  1. 安装json-server

    bash 复制代码
    npm install -g json-server
  2. 创建db.json文件,定义Mock数据:

    json 复制代码
    {
      "users": [
        { "id": 1, "name": "jane", "age": 20 },
        { "id": 2, "name": "kevin", "age": 25 }
      ],
      "products": [
        { "id": 1, "name": "手机", "price": 3000 }
      ]
    }
  3. 启动Mock Server:

    bash 复制代码
    json-server --watch db.json --port 3000

    访问http://localhost:3000/users,就能看到上面定义的用户数据了。

2. 在Cypress中调用Mock Server

测试时直接请求本地Mock Server的接口,不用依赖后端:

javascript 复制代码
it('调用自定义Mock Server的接口', () => {
  // 访问Mock Server的用户列表接口
  cy.request('GET', 'http://localhost:3000/users')
    .then((response) => {
      expect(response.status).to.equal(200)
      expect(response.body.length).to.equal(2)
      expect(response.body[0].name).to.equal('jane')
    })

  // 也可以结合UI测试
  cy.visit('/user-list') // 页面里的接口地址指向http://localhost:3000/users
  cy.get('[data-cy=user-item]').should('have.length', 2)
})

四、Mock的最佳实践

  1. 区分环境 :开发环境用Mock,测试环境用真实接口,在cypress.json里通过环境变量控制:

    json 复制代码
    {
      "env": {
        "useMock": true, // true用Mock,false用真实接口
        "mockBaseUrl": "http://localhost:3000"
      }
    }
  2. Mock数据贴近真实:尽量让Mock数据的格式、字段和真实接口一致,避免后期切换时出现兼容问题。

  3. 清理Mock状态 :用cy.intercept()时,在afterEach里重置拦截器,避免影响其他用例:

    javascript 复制代码
    afterEach(() => {
      cy.intercept('GET', '/api/products', (req) => {
        req.continue() // 让请求走真实接口
      })
    })
相关推荐
学Java的bb6 小时前
JavaWeb-后端Web实战(IOC + DI)
前端
pe7er7 小时前
React Native 多环境配置全攻略:环境变量、iOS Scheme 和 Android Build Variant
前端·react native·react.js
柯北(jvxiao)7 小时前
Vue vs React 多维度剖析: 哪一个更适合大型项目?
前端·vue·react
JefferyXZF7 小时前
Next.js 中间件:掌握请求拦截与处理的核心机制(六)
前端·全栈·next.js
知识分享小能手8 小时前
Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
前端·javascript·css·vue.js·学习·typescript·vue3
石小石Orz8 小时前
React生态蓝图梳理:前端、全栈与跨平台全景指南
前端
袁煦丞8 小时前
8.12实验室 指尖魔法变出艺术感 Excalidraw:cpolar内网穿透实验室第495个成功挑战
前端·程序员·远程工作
烛阴8 小时前
Dot
前端·webgl
Gene_20229 小时前
使用行为树控制机器人(三) ——通用端口
前端·机器人
excel9 小时前
JavaScript 中的二进制数据:ArrayBuffer 与 SharedArrayBuffer 全面解析
前端