十二、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() // 让请求走真实接口
      })
    })
相关推荐
ai小鬼头24 分钟前
创业小公司如何低预算打造网站?熊哥的实用建站指南
前端·后端
阿星做前端31 分钟前
聊聊前端请求拦截那些事
前端·javascript·面试
阿凤2135 分钟前
在UniApp中防止页面上下拖动的方法
前端·uni-app
拾光拾趣录43 分钟前
DocumentFragment:高性能DOM操作
前端·dom
归于尽1 小时前
从JS到TS:我们放弃了自由,却赢得了整个世界
前端·typescript
palpitation971 小时前
Fitten Code使用体验
前端
byteroycai1 小时前
用 Tauri + FFmpeg + Whisper.cpp 从零打造本地字幕生成器
前端
用户1512905452201 小时前
C 语言教程
前端·后端
UestcXiye1 小时前
Rust Web 全栈开发(十):编写服务器端 Web 应用
前端·后端·mysql·rust·actix
kuekuatsheu2 小时前
《前端基建实战:高复用框架封装与自动化NPM发布指南》
前端