如何编写单元测试枚举tRPC路由并检查所有端点均附加认证中间件?
如何编写单元测试枚举tRPC路由并检查所有端点均附加认证中间件?
这个问题我刚好碰到过!要解决这个问题,核心是利用tRPC Router内部的定义结构来枚举所有端点,然后逐个检查是否挂载了你的认证中间件。下面是具体的实现步骤和代码示例:
第一步:给认证中间件添加唯一标识
首先,为了能在测试中准确识别出你的auth中间件,最好给它加一个自定义的标识属性——毕竟直接对比函数引用可能会因为闭包或者实例化的问题出现误判。
修改你的auth中间件函数,像这样:
// 假设这是你的auth中间件定义 export function auth(authMethods: AuthMethod[]) { const authMiddleware = async (opts: MiddlewareOpts) => { // 你的认证逻辑:验证token、检查权限等 const authenticatedUser = await validateAuth(opts.ctx, authMethods); return opts.next({ ctx: { ...opts.ctx, user: authenticatedUser } }); }; // 添加自定义标识,方便测试时识别 authMiddleware.__isAuthMiddleware = true; return authMiddleware; }
第二步:编写单元测试枚举所有端点
tRPC的Router实例内部有一个_def属性,里面的procedures字段会列出所有你定义的端点(比如getOne、getTwo),每个端点的middleware数组就是挂载的所有中间件集合。我们可以遍历这个集合,逐个检查是否包含带标识的auth中间件。
以Jest测试为例:
import { accountsRouter } from './path-to-your-accounts-router'; describe('tRPC 路由认证检查', () => { it('所有端点必须附加认证中间件', () => { // 获取路由下所有的端点定义 const allProcedures = accountsRouter._def.procedures; // 遍历每个端点,检查认证中间件是否存在 Object.entries(allProcedures).forEach(([procedureName, procedureDef]) => { const hasAuthMiddleware = procedureDef.middleware.some( middleware => middleware.__isAuthMiddleware === true ); // 如果某个端点没加auth,测试会抛出明确的错误提示 expect(hasAuthMiddleware).toBe( true, `端点 "${procedureName}" 未附加认证中间件,存在安全风险!` ); }); }); });
第三步(可选):设置例外端点列表
如果确实有少数公开端点不需要认证,你可以添加一个例外列表,让测试跳过这些端点的检查:
// 允许无需认证的端点列表 const allowedUnauthenticatedEndpoints = ['publicHealthCheck', 'publicSignup']; // 在遍历的时候跳过这些端点 Object.entries(allProcedures).forEach(([procedureName, procedureDef]) => { if (allowedUnauthenticatedEndpoints.includes(procedureName)) { return; } // 检查认证中间件的逻辑... });
补充说明
可能你会担心_def是tRPC的内部属性,会不会在未来版本变更?其实在测试环境下使用是完全安全的——我们只是读取它做断言,不会修改内部结构。目前tRPC的公共API还没有提供枚举路由的方法,所以这是最直接可靠的方案。
备注:内容来源于stack exchange,提问作者Lqueryvg
相关产品推荐
相关产品推荐

