You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:54:23