如何在Create React App中使用Jest模拟react-adal进行单元测试
解决react-adal导致单元测试全部失败的问题
我之前在使用Create React App v2 + Jest + react-testing-library搭配react-adal做授权时,也碰到过一模一样的问题——加完ADAL层后所有测试都报{ message: 'User login is required', msg: 'login required' }错误。折腾了好一阵,总结了几个亲测有效的解决方案,分享给你:
方案1:正确Mock react-adal的核心方法
很多时候mock没生效,是因为没有覆盖到runWithAdal和withAdalLoginApi这两个关键方法。你可以在测试文件(比如App.test.js)顶部添加如下mock代码:
// App.test.js jest.mock('react-adal', () => ({ // 模拟runWithAdal:直接执行传入的回调,跳过ADAL登录流程 runWithAdal: jest.fn((adalConfig, callback) => callback()), // 模拟withAdalLoginApi:直接返回原组件,不添加授权包裹层 withAdalLoginApi: jest.fn(() => (Component) => Component), // 如果你的项目用到了react-adal的其他方法(比如withAdalApiFetch),也要在这里一并mock }));
这个方案的核心是让测试环境完全绕开ADAL的授权校验逻辑,直接执行原本要在登录后才会运行的代码。
方案2:模拟已登录的ADAL上下文状态
如果你的组件内部依赖ADAL的用户认证状态,可以mock ADAL的上下文对象,让它返回“已登录”的状态。比如如果你的项目有单独的adal.config.js文件,可以这样mock:
// App.test.js jest.mock('./adal.config', () => ({ adalConfig: { // 保留你的基础配置,或者按需修改 clientId: 'test-client-id', redirectUri: 'http://localhost:3000' }, // 模拟getAdalContext方法,返回已登录的用户信息 getAdalContext: jest.fn(() => ({ userInfo: { isAuthenticated: true, userName: 'test-user@example.com' }, acquireToken: jest.fn(() => Promise.resolve('fake-token')) })) }));
如果你的组件用了useAdal钩子,也要对应mock这个钩子:
jest.mock('react-adal', () => ({ // 其他mock... useAdal: jest.fn(() => ({ adalContext: { userInfo: { isAuthenticated: true } }, login: jest.fn(), logout: jest.fn() })) }));
方案3:直接渲染内层App组件,跳过ADAL外层包裹
如果你的index.js是通过runWithAdal启动应用,并且App.js被withAdalLoginApi包裹,那测试时可以直接导入未被包裹的App组件(如果有的话),或者调整测试的导入路径:
比如原本你可能在测试里导入的是从index.js导出的包裹后的组件:
import App from './index';
改成直接导入App.js里的原始组件:
import App from './App';
这样就能绕开ADAL的外层授权逻辑,直接测试业务组件本身。
注意事项
- 确保你的mock代码放在测试文件的最顶部,在导入任何依赖之前执行;
- 如果有多个测试文件都碰到这个问题,可以把mock逻辑放到
src/setupTests.js里,让所有测试自动应用这个mock; - 测试时尽量专注于业务逻辑,授权相关的逻辑可以单独写集成测试去验证,单元测试没必要重复校验ADAL的功能。
内容的提问来源于stack exchange,提问作者aromanarguello
相关产品推荐
相关产品推荐

