一个好的前端mock工具,可以有效的提高前端开发效率

常用的mock方案这里不做过多介绍,可以自行搜索

本文要介绍的mock工具msw,它通过service worker来做请求拦截:

Mock Service Worker

优点总结

  • 集成于前端,不需要写node中间件(比如express, koa)
  • 语法基本和express一致
  • 直接通过chrome快速debugger
  • 即可用于前端开发,也可用于单元测试,只需要写一份mocker
  • 可在build环境使用mock
  • 不存在跨域问题

安装方式

Install - Getting Started

handler.ts拆分

示例中,创建了src/mocks/modules文件夹,旨在按不同模块进行mock,而不是将所有模拟请求都放在handler.ts中,这样太乱了!

建议优化start worker配置

建议优化start worker配置

基于官网的示例,改成如下配置:

// src/index.tsx

// ...

function renderApp() {
  ReactDOM.render(
    <App />,
    document.getElementById('root'),
  );
}

// __ENV_DEV__   __MOCK_IN_PRODUCTION__ -> 全局替换变量
// __ENV_DEV__ 开发环境
// __MOCK_IN_PRODUCTION__ 在build环境中使用mock
if (__ENV_DEV__ || __MOCK_IN_PRODUCTION__) {
  import('./mocks/browser').then(async ({ default: worker }) => {
    await worker.start();
    renderApp();
  });
} else {
  renderApp();
}

src/index.tsx

为什么这样做?

  • vite默认不支持require
  • 通过动态import可生成单独的chunk,结合全局替换变量,可实现按需加载,且不会对代码打包体积造成影响

启动运行

当chrome console中打印了 [MSW] Mocking enabled,表示模拟生效;

查看模拟的请求,会发现Status Code: 200 OK (from service worker)

warning处理

当请求没有被mocker实现的时候,比如任意图片资源,在控制台中会显示对应的warning,如下:

虽然无伤大雅,但看起来确实烦躁,不过处理方式很简单,只需在start worker配置中添加属性(onUnhandledRequest)即可:

if (__ENV_DEV__ || __MOCK_IN_PRODUCTION__) {
  import('./mocks/browser').then(async ({ default: worker }) => {
    await worker.start({ onUnhandledRequest: 'bypass' });
    renderApp();
  });
} else {
  renderApp();
}

单元测试

Node - Getting Started

这里有个小坑,当其他测试用例使用到jest.mock('axios')时,需要在头部添加jest.unmock('axios'),要不然mocker无法生效!!

代码如下:

import { XxxService } from '@/services';

jest.unmock('axios'); // 当其他测试用到jest.mock('axios')时,需要保留这段语句

describe('mock api', () => {
  it('mock queryUsers', async () => {
    const res = await XxxService.queryUsers();

    expect(res.users.length).not.toBe(0);
    expect(res.defaultUser).toBeTruthy();
  });
});

关于fallback mode

以下几种情形会变成fallback mode:

  • 浏览器不支持service Worker
  • 域名未开启https,且域名不是localhost或者127.0.0.1

TIPS: 若开启https,同时需要安装证书!!没有证书msw会直接报错,导致无法访问页面

fallback mode会导致network中不会出现对应接口日志,只能在console中查看接口信息,效果如下图:

解决fallback mode

解决fallback mode