如何用Sinon Stub模拟React自定义Hook并解决相关报错
问题解决方案
一、用Sinon正确模拟React自定义Hook
你的错误根源是直接在组件外部调用React Hook,违反了Hook的使用规则。正确的做法是Stub整个Hook的导出模块,让组件在测试时调用我们的Mock版本,而非真实Hook。
实现代码
import * as useApiDataModule from "../path/to/your/useApiData"; // 替换为Hook的实际路径 export function mockGetCase(sinonSandbox: SinonSandbox = sinon.createSandbox()) { // 模拟useQuery的返回结构(组件会依赖这些属性) const mockUseQueryResult = { data: caseMockApiData, isLoading: false, isSuccess: true, error: null // 可根据组件实际使用的属性补充 }; // Stub Hook的getCase方法 const mockGetCase = sinonSandbox.stub().returns(mockUseQueryResult); // Stub整个useApiData Hook的返回值 sinonSandbox.stub(useApiDataModule, "useApiData").returns({ api: { getCase: mockGetCase }, networkError: null }); return sinonSandbox; }
关键说明
- 不要直接调用
useApiData(),而是通过Stub模块导出的方式,替换Hook的实现 - 模拟的
getCase必须返回符合useQuery的结构(而非直接返回Promise),因为原Hook中getCase的返回值是useQuery的结果对象
二、解决MSW的绝对URL错误
报错是因为两个原因:getSecurityTokenForApp中的相对路径请求未被拦截,且API地址可能未使用绝对路径。
修复步骤
- 拦截/token请求:在MSW中添加对token接口的模拟,避免真实请求触发错误
- 确保API地址为绝对路径:检查
environment.url.case是否为完整的绝对URL(如https://your-api-domain/case)
修正后的MSW代码
const server = setupServer( // 模拟案件接口 rest.get(`${environment.url.case}/api/case/:caseId`, (req, res, ctx) => { return res(ctx.json(caseMockApiData)); }), // 模拟token获取接口 rest.post("/token", (req, res, ctx) => { return res(ctx.text("mock-security-token")); // 返回模拟的token }) ); before(() => server.listen()); afterEach(() => server.resetHandlers()); after(() => server.close());
补充说明
如果environment.url.case是相对路径,需在测试环境中配置为绝对路径,或直接在MSW中写死绝对URL(如https://test-api.com/case/api/case/:caseId)。
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

