使用React Testing Library与Jest测试返回空片段的Login组件
测试思路
这个组件没有可交互的可见UI,核心逻辑全部在挂载时执行的副作用里,测试不需要关注DOM渲染结果,只需要覆盖msalInstance方法的所有逻辑分支即可。测试前先mock MSAL依赖,避免真实发起身份认证请求。
前置Mock配置
在测试文件顶部先mock认证模块,替换所有MSAL方法为Jest mock函数,同时处理控制台日志避免测试输出脏数据:
import { render, waitFor } from '@testing-library/react'; import { Login } from './Login'; import { msalInstance } from './authConfig'; // Mock整个MSAL配置模块 jest.mock('./authConfig', () => ({ msalInstance: { handleRedirectPromise: jest.fn(), getAllAccounts: jest.fn(), loginRedirect: jest.fn(), } })); beforeEach(() => { // 监听console.error,不输出实际日志同时保留断言能力 jest.spyOn(console, 'error').mockImplementation(() => {}); // 每次测试前重置所有mock的调用记录 jest.clearAllMocks(); }); afterEach(() => { // 还原console原生方法,避免影响其他测试 console.error.mockRestore(); });
核心测试用例
1. 重定向回调返回有效token时,不触发登录跳转
当handleRedirectPromise返回有效token响应,逻辑不会进入未登录判断分支,不需要调用账号查询和登录方法:
test('拿到有效重定向token时不触发登录', async () => { // 模拟重定向回调返回有效登录凭证 msalInstance.handleRedirectPromise.mockResolvedValue({ accessToken: 'test-valid-token', account: { name: 'test-user' } }); render(<Login />); await waitFor(() => { expect(msalInstance.getAllAccounts).not.toHaveBeenCalled(); expect(msalInstance.loginRedirect).not.toHaveBeenCalled(); }); });
2. 无回调token且无已登录账号时,触发重定向登录
当handleRedirectPromise返回空值,且本地查询不到任何已登录账号缓存时,必须调用loginRedirect拉起微软登录页:
test('无有效token且无登录账号时触发重定向登录', async () => { msalInstance.handleRedirectPromise.mockResolvedValue(null); // 模拟本地无已登录账号 msalInstance.getAllAccounts.mockReturnValue([]); render(<Login />); await waitFor(() => { expect(msalInstance.getAllAccounts).toHaveBeenCalledTimes(1); expect(msalInstance.loginRedirect).toHaveBeenCalledTimes(1); }); });
3. 无回调token但存在已登录账号时,不触发重复登录
当重定向没有返回新token,但本地已经缓存了有效登录账号,说明用户处于已登录状态,不需要重复拉起登录流程:
test('存在已登录账号时不触发重复登录', async () => { msalInstance.handleRedirectPromise.mockResolvedValue(null); // 模拟本地存在已登录账号 msalInstance.getAllAccounts.mockReturnValue([{ username: 'test@example.com' }]); render(<Login />); await waitFor(() => { expect(msalInstance.loginRedirect).not.toHaveBeenCalled(); }); });
4. 认证流程抛错时正确捕获并打印日志
当handleRedirectPromise执行异常(比如回调参数非法、网络错误、用户取消登录),组件要正确捕获错误,不触发崩溃:
test('认证流程报错时打印错误日志', async () => { const testError = new Error('MSAL redirect handle failed: invalid state'); msalInstance.handleRedirectPromise.mockRejectedValue(testError); render(<Login />); await waitFor(() => { expect(console.error).toHaveBeenCalledWith(testError); expect(msalInstance.loginRedirect).not.toHaveBeenCalled(); }); });
注意事项
- 所有涉及Promise的异步断言必须放在
waitFor回调中,或者手动return Promise让Jest等待异步执行完成,避免测试提前结束导致假通过 - 组件返回的空Fragment没有可查询的DOM节点,不需要写渲染相关断言
- 如果后续给组件加了加载中提示、错误提示等UI,直接补充对应DOM断言即可,现有逻辑测试用例不需要改动
内容的提问来源于stack exchange,提问作者Siri
相关产品推荐
相关产品推荐

