使用Cypress模拟OAuth登录会话后个人页显示无资料问题排查
问题分析
首页能正常显示登录状态,是因为你通过cy.intercept拦截了/api/auth/session接口,返回了模拟的会话数据,前端useSession能正确拿到登录信息。但个人资料页的userInfo是通过服务器端的getServerSideProps直接调用getUserInfo操作数据库获取的——测试时这个查询会访问真实数据库,而数据库中没有test0000这个slug的用户,因此返回null,导致页面显示“No profile”。
解决方案
以下是三种可行的解决思路,按场景适配选择:
方案1:测试环境下Mock数据库查询函数
直接修改getUserInfo的实现,在测试环境跳过真实数据库查询,返回模拟数据:
// @scripts/prisma/getUserInfo.ts import { User } from "@prisma/client"; export async function getUserInfo(slug: string): Promise<User | null> { // 测试环境直接返回模拟数据 if (process.env.NODE_ENV === "test") { return { bio: "Lorem Testum", name: "test", email: "test@test.com", slug: "test0000", id: "strasnedlouhejstring", isActive: true, // 补充User类型要求的其他必填字段(如createdAt、updatedAt) createdAt: new Date(), updatedAt: new Date() }; } // 生产/开发环境的真实数据库查询逻辑(保留原代码) // ... }
然后在Cypress配置中设置测试环境变量:
// cypress.config.js module.exports = defineConfig({ env: { NODE_ENV: "test" }, // 其他Cypress配置 });
方案2:将数据库查询改为API调用并拦截
把服务器端直接调用数据库的逻辑改成调用内部API,再用Cypress拦截该API返回模拟数据:
步骤1:创建用户信息API路由
新建pages/api/user/[slug].ts:
import { getUserInfo } from "@scripts/prisma/getUserInfo"; import type { NextApiRequest, NextApiResponse } from "next"; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const { slug } = req.query; if (typeof slug !== "string") { return res.status(400).json({ error: "Invalid slug" }); } const user = await getUserInfo(slug); res.status(200).json(user); }
步骤2:修改getServerSideProps调用API
export const getServerSideProps: GetServerSideProps = async (context) => { const slug = context.query.userProfile?.toString(); if (slug) { // 替换原数据库查询为API调用 const res = await fetch(`http://localhost:3000/api/user/${slug}`); const user = await res.json(); if (user) { return { props: { userInfo: user }, }; } } return { props: { userInfo: null }, }; };
步骤3:更新Cypress命令与测试
在login命令中添加API拦截:
Cypress.Commands.add("login", () => { cy.intercept("/api/auth/session", { fixture: "session.json" }).as("session"); // 拦截用户信息API,返回模拟数据 cy.intercept("/api/user/test0000", { fixture: "userInfo.json" }).as("userInfo"); cy.setCookie("next-auth.session-token", "testcookie"); Cypress.Cookies.preserveOnce("next-auth.session-token"); });
创建cypress/fixtures/userInfo.json:
{ "bio": "Lorem Testum", "name": "test", "email": "test@test.com", "slug": "test0000", "id": "strasnedlouhejstring", "isActive": true, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z" }
修改测试代码验证个人资料页:
describe("Cypress login", () => { it("should display user profile correctly", () => { cy.login(); cy.visit("/userProfile/test0000"); // 替换为你的个人资料页实际路径 cy.wait(["@session", "@userInfo"]); cy.get("h1").should("not.contain", "No profile"); cy.get(".profile-bio").should("contain", "Lorem Testum"); // 替换为页面实际元素选择器 }); });
方案3:组件测试直接传递Props
如果仅需验证组件渲染逻辑,可使用Cypress组件测试,直接给UserProfile组件传递userInfo:
import UserProfile from "../../pages/userProfile/[userProfile]"; describe("UserProfile Component", () => { it("renders profile content when userInfo exists", () => { cy.mount(<UserProfile userInfo={{ bio: "Lorem Testum", name: "test", email: "test@test.com", slug: "test0000", id: "strasnedlouhejstring", isActive: true, createdAt: new Date(), updatedAt: new Date() }} />); cy.get("h1").should("not.contain", "No profile"); }); });
内容的提问来源于stack exchange,提问作者MRZTyy
相关产品推荐
相关产品推荐

