全栈开发的“影分身”之术(mock):别再手动造数据了,你的 CRUD 不配让我等!

从前端 React 到后端 NestJS,一套基于 Mockjs 的全链路"摸鱼"指南(不是,是提效指南)。


开篇:那个深夜,我和后端的"爱恨情仇"

还记得那个周五的晚上吗?你兴致勃勃地打开了 VS Code,准备大干一场,写一个惊天地泣鬼神的管理后台。你设计好了页面,配置好了路由,甚至把 axios 都 import 进来了。

然后,你兴冲冲地去找后端小哥:"哥,把用户列表接口给我,我要联调了!"

后端小哥头也不抬,冷冷地回了一句:"忙着呢,实体类还没建好,JWT 鉴权还没写完,Redis 缓存还没配,下周一吧。"

周一??? 我的热血只在这一秒沸腾,你让我等到周一?

那一刻,我仿佛听到了产品狗在工位旁磨刀的声音。

于是,我悟了。全栈开发的第一课,不是写代码,而是学会"自给自足"。 既然你不动,那我就自己造一个"你"出来。

这就是今天我要分享的主角------Mock(模拟数据)

一、 Mock 是什么?是前端的"海市蜃楼",也是后端的"单元测试"

在进入正题前,我们得先统一一下价值观。

Mock 的本质,就是"欺骗"。 欺骗你的前端代码,让它以为自己正在和一个高大上的服务器进行着 500ms 的延迟交互,实际上,数据就在你本地的内存里。

它有两大核心价值:

  1. 前端独立开发: 不用看后端脸色,接口文档在手,天下我有。
  2. 后端接口自测: 在数据库还没建好时,先跑通业务逻辑。

今天,我就以一个AI 全栈项目为例,带大家看看如何在 React 前端和 NestJS 后端同时施展"影分身"之术。

二、 前端篇:Mockjs,那个能造"假"乱真的库

在 React + TypeScript 的世界里,Mockjs 是我们的老伙计。它不仅能造数据,还能造"随机"的数据。

1. 假装我们有 45 条文章数据

在项目中,我们通常会遇到分页列表。按照常规思路,我们要写一堆死数据。但在 Mock 的世界里,一行代码搞定:

javascript 复制代码
// mock/posts.ts
import Mock from 'mockjs';

const tags = ["前端", "后端", "职场", "AI", "副业", "面经", "算法"];

const posts = Mock.mock({
  'list|45': [  // 看好了,我要造45条数据!
    {
      title: '@ctitle(8, 20)', // 随机中文标题,8到20个字
      brief: '@ctitle(20, 100)', // 随机中文摘要
      totalComments: '@integer(1, 30)', // 随机评论数
      totalLikes:'@integer(0, 500)', // 随机点赞数
      publishedAt: '@datetime("yyyy-MM-dd HH:mm")', // 随机时间
      user: {
        name: '@cname', // 随机中文姓名
        avatar: '@image(300x200)' // 连头像都是随机生成的图片链接!
      },
      tags: () => Mock.Random.pick(tags, 2), // 随机从数组里挑2个标签
      id: '@increment(1)' // 自增ID
    }
  ]
}).list;

技巧点拨:

  • @ctitle@cname@image 这些都是 Mockjs 的"语法糖"。用它,你再也不用写 const name = '张三' 这种枯燥的代码了。
  • 'list|45' 这种写法,直接生成一个长度为 45 的数组。分页测试?拿捏得死死的。

2. 拦截请求,返回"假"数据

有了数据,我们还得拦截前端发出来的请求。在 Vite 或 Webpack 的代理配置下,我们可以直接写一个接口路由:

arduino 复制代码
// mock/posts.ts
export default [
  {
    url: '/api/posts',
    method: 'get',
    response: ({ query }) => {
      const { page = '1', limit = '10' } = query;
      const currentPage = parseInt(page, 10);
      const size = parseInt(limit, 10);

      // 1. 先算总数
      const total = posts.length; 
      // 2. 再算切片起点
      const start = (currentPage - 1) * size;
      // 3. 切片终点
      const end = start + size;
      // 4. 截取数据
      const paginatedData = posts.slice(start, end);

      return {
        code: 200,
        msg: 'success',
        items: paginatedData,
        pagination: {
          current: currentPage,
          limit: size,
          total,
          totalPage: Math.ceil(total / size)
        }
      }
    }
  }
]

这就是 Mock 的核心逻辑: 接口文档怎么写的,我就怎么 mock。前端代码里,你甚至感觉不到这是一份假数据。

三、 后端篇:NestJS + Prisma,数据库还没建好?先"流"一把!

你以为 Mock 只是前端的事?错!作为全栈工程师,我们要在后端也搞点事情。

在 NestJS 项目中,我们通常使用 Prisma 作为 ORM。但在 npx prisma migrate dev 之前,我们怎么测试接口的逻辑是否通顺?比如那个酷炫的 SSE (Server-Sent Events) 流式输出

场景: 我们正在开发一个 AI ChatBot,需要像 ChatGPT 一样逐字输出。

如果这时候去调用真实的 DeepSeek 或 OpenAI 接口,不仅慢,还费钱,网络波动还会导致测试失败。

解决方案: 在 Controller 里写一个 rawResponse,直接模拟流式输出。

typescript 复制代码
// ai.controller.ts
import { Controller, Post, Req, Res, Get } from '@nestjs/common';

@Controller('api/ai')
export class AiController {
  // rawResponse 用于自定义原始 HTTP 响应(如流式输出)
  @Post('chat')
  async chat(@Req() req, @Res() res) {
    // 1. 设置响应头,告诉浏览器:我要开始流式传输了!
    res.setHeader('Content-Type', 'text/plain;charset=utf-8');
    res.setHeader('Transfer-Encoding', 'chunked');
    res.setHeader('x-vercel-ai-data-stream', 'v1');

    // 2. 模拟 AI 生成的文本
    const mockText = "你好!我是你的AI助手。正在使用Mock技术假装思考中...";
    
    // 3. 模拟逐字输出(打字机效果)
    for (let i = 0; i < mockText.length; i++) {
      const char = mockText[i];
      // 这里模拟 ai-sdk 的格式
      res.write(`0:${JSON.stringify(char)}\n`);
      // 加点延迟,更有真实感
      await new Promise(resolve => setTimeout(resolve, 50));
    }

    // 4. 结束响应
    res.end();
  }
}

为什么要这么做?

在 NestJS 开发中,利用 Mock 进行逻辑隔离 非常重要。你可以先把接口的结构、状态码、流式传输的逻辑跑通。等 Prisma Client 生成好了,再把里面的 mockText 替换成真实的 this.aiService.stream() 即可。

四、 进阶:Mock 的"鉴权"陷阱与绕过

在全栈项目中,最难搞的往往不是数据,而是权限校验

比如,你的文章发布接口 POST /api/posts 加了 @UseGuards(AuthGuard('jwt'))。这时候,前端调用 Mock 接口,因为没有 Token,直接被 401 拦截了。

怎么办?两个方案:

  1. 环境变量开关: 在 NestJS 的 Guard 里加个判断,如果是 process.env.NODE_ENV === 'development',直接放行。
  2. Mock 也要有仪式感: 既然要像,那就连 Token 验证都要像。

我们可以利用 jsonwebtoken 在 Mock 接口里签发一个"万能钥匙":

javascript 复制代码
// mock/auth.ts
import * as jwt from 'jsonwebtoken';

const secret = "bld1235swsad!";

export default [
  {
    url: '/api/auth/login',
    method: 'post',
    response: ({ body }) => {
      const { name, password } = body;
      // 假装验证用户名密码
      if (name === 'admin' && password === '123456') {
        // 签发一个假 Token
        const token = jwt.sign(
          { user: { id: 1, name: "admin" } }, 
          secret, 
          { expiresIn: 3600 }
        );
        return { access_token: token, user: { id: 1, name: "admin" } };
      }
      return { code: 401, message: '鉴权失败' };
    }
  }
]

这样,你的前端在开发环境下,既能测试登录流程,又能拿到 Token 去访问受保护的接口,完美闭环。

五、 总结:做一个"善始善终"的全栈工程师

通过这篇文章,我希望你掌握了以下 Mock 核心技巧

  1. 前端 Mockjs: 利用 Mock.mock() 生成随机数据,利用 slice 实现分页,完全隔离于后端。
  2. 后端 NestJS: 利用 rawResponse 模拟流式输出(SSE),在数据库未就位时先行开发业务逻辑。
  3. 全链路打通: 即使有 JWT 鉴权,也能通过 Mock 登录接口生成合法 Token,保证开发体验流畅。

最后送给大家一句话:

"磨刀不误砍柴工,Mock 好了早下班。"

不要让你的宝贵时间浪费在等待后端"修仙"或者产品经理"改需求"上。利用 Mock 技术,把命运掌握在自己手里!

如果你觉得这篇文章对你有帮助,别忘了点赞、收藏、分享三连!有任何问题,欢迎在评论区留言,我将化身"行走的 Mock 工具人"为你解答。

我是爱吃火锅的程序员,我们下期再见!


附录:文中提到的核心依赖库

为了方便大家复现,整理了一下文中全栈项目涉及的核心技术栈:

表格

层级 技术栈 用途
前端框架 React + TS 构建用户界面
前端路由 React-Router-Dom 实现 SPA 单页应用路由
状态管理 Zustand 轻量级全局状态管理
接口模拟 Mockjs 前端拦截请求,生成随机数据
后端框架 NestJS 企业级 Node.js 框架
数据库 Prisma + PostgreSQL ORM 与 关系型数据库
鉴权 JWT 用户身份令牌验证
AI 工具 LangChain/Coze AI 业务逻辑编排
相关推荐
亿元程序员1 小时前
小伙伴说这个撕胶带游戏很火很解压,于是我连夜做了一个Cocos教程...
前端
如果超人不会飞1 小时前
一文读懂 TinyRobot:前端 AI 组件库定位、价值与适用场景
前端·vue.js
如果超人不会飞1 小时前
用TinyRobot Welcome组件打造贴心的AI助手欢迎页
前端·vue.js
悟空瞎说1 小时前
Compose内嵌Flutter混合开发详解:页面嵌入、引擎缓存与双向通信完整实战
前端
如果超人不会飞1 小时前
TinyRobot DragOverlay轻松实现AI对话中的拖拽上传
前端·vue.js
elirlove11 小时前
打造属于自己的网页工匠台:HTML在线编辑器技术深度解析
前端·编辑器·html
wh_xmy1 小时前
从HTML5到AI,我的前端十年
前端·程序人生·十年程序员·ai 对前端的影响
程序员mine1 小时前
Web服务密码存储安全详解:从哈希到密钥派生的演进
前端·后端
如果超人不会飞1 小时前
TinyRobot Sender打造强大的AI聊天输入体验
前端·vue.js