如何使用Jasmine编写Angular中AWS Cognito authenticateUser的测试用例?
没问题,我来帮你搞定Angular组件里Cognito认证的Jasmine测试用例!咱们一步步拆解,从准备工作到核心测试场景都给你安排明白:
一、测试前的准备工作
首先要做的是mock AWS Cognito的所有依赖类,绝对不能让测试调用真实的Cognito服务(否则测试会不稳定、依赖网络,还可能产生无效请求)。我们用Jasmine的spyOn和createSpyObj来模拟这些对象:
// 先声明全局的AWSCognito模拟对象(避免TS报错) declare const AWSCognito: any; describe('YourAuthComponent', () => { let component: YourAuthComponent; let fixture: ComponentFixture<YourAuthComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [YourAuthComponent] // 这里如果组件有其他依赖(比如Router、Toast服务),也要一并mock }).compileComponents(); }); beforeEach(() => { // 重置所有mock,避免测试用例之间互相影响 jasmine.clearAllSpies(); // 1. 模拟CognitoUserPool构造函数,返回一个空的spy对象 const mockUserPool = jasmine.createSpyObj('CognitoUserPool', ['']); spyOn(AWSCognito, 'CognitoUserPool').and.returnValue(mockUserPool); // 2. 模拟AuthenticationDetails构造函数 spyOn(AWSCognito, 'AuthenticationDetails'); // 3. 模拟CognitoUser构造函数,重点给authenticateUser方法做spy const mockCognitoUser = jasmine.createSpyObj('CognitoUser', ['authenticateUser']); spyOn(AWSCognito, 'CognitoUser').and.returnValue(mockCognitoUser); // 初始化组件 fixture = TestBed.createComponent(YourAuthComponent); component = fixture.componentInstance; fixture.detectChanges(); }); });
二、核心测试用例编写
1. 测试认证对象的初始化逻辑
验证组件是否正确创建了Cognito的各类实例,并且传入了正确的参数:
it('should initialize Cognito objects with correct pool data and user credentials', () => { // 给组件设置测试用的用户名和密码 component.username = 'test-user-001'; component.password = 'test-pass-123'; // 假设触发认证的方法叫login(),调用它 component.login(); // 验证UserPool是否用预设的poolData创建 expect(AWSCognito.CognitoUserPool).toHaveBeenCalledWith({ UserPoolId: '<UserPoolId>', ClientId: '<ClientId>' }); // 验证AuthenticationDetails是否传入了正确的用户名密码 expect(AWSCognito.AuthenticationDetails).toHaveBeenCalledWith({ Username: 'test-user-001', Password: 'test-pass-123' }); // 验证CognitoUser是否用正确的用户名和UserPool实例创建 expect(AWSCognito.CognitoUser).toHaveBeenCalledWith({ Username: 'test-user-001', Pool: AWSCognito.CognitoUserPool.calls.mostRecent().returnValue }); });
2. 测试认证成功的场景
验证当authenticateUser的onSuccess回调触发时,组件的后续行为是否符合预期(比如跳转页面、保存token、更新用户状态等):
it('should handle authentication success correctly', () => { // 获取mock的CognitoUser实例 const mockCognitoUser = AWSCognito.CognitoUser.calls.mostRecent().returnValue; // 假设组件成功后会调用navigateToHome方法,先给它做spy spyOn(component, 'navigateToHome'); // 触发登录逻辑 component.username = 'test-user-001'; component.password = 'test-pass-123'; component.login(); // 获取authenticateUser调用时传入的回调对象 const authCallbacks = mockCognitoUser.authenticateUser.calls.mostRecent().args[1]; // 手动触发onSuccess回调,传入模拟的认证结果 const mockAuthResult = { idToken: { getJwtToken: () => 'mock-jwt-token-123' } }; authCallbacks.onSuccess(mockAuthResult); // 验证组件是否执行了成功后的逻辑 expect(component.navigateToHome).toHaveBeenCalled(); // 如果组件会保存token,也可以验证: // expect(component.userToken).toBe('mock-jwt-token-123'); });
3. 测试认证失败的场景
验证当认证失败时,组件是否正确处理错误(比如显示错误提示、重置表单等):
it('should handle authentication failure correctly', () => { const mockCognitoUser = AWSCognito.CognitoUser.calls.mostRecent().returnValue; // 假设组件会调用showErrorAlert显示错误,给它做spy spyOn(component, 'showErrorAlert'); // 触发登录逻辑(用错误的凭证) component.username = 'wrong-user'; component.password = 'wrong-pass'; component.login(); // 获取回调对象,手动触发onFailure const authCallbacks = mockCognitoUser.authenticateUser.calls.mostRecent().args[1]; const mockError = new Error('Invalid username or password'); authCallbacks.onFailure(mockError); // 验证错误提示是否被正确调用 expect(component.showErrorAlert).toHaveBeenCalledWith('Invalid username or password'); });
4. 测试特殊回调场景(可选)
如果你的用户池开启了首次登录强制改密码,还可以测试newPasswordRequired回调:
it('should handle new password required scenario', () => { const mockCognitoUser = AWSCognito.CognitoUser.calls.mostRecent().returnValue; // 假设组件会打开改密码弹窗,给它做spy spyOn(component, 'openNewPasswordModal'); component.login(); // 获取回调对象,手动触发newPasswordRequired const authCallbacks = mockCognitoUser.authenticateUser.calls.mostRecent().args[1]; const mockUserAttributes = { email: 'test@example.com' }; const mockRequiredAttributes = ['email_verified']; authCallbacks.newPasswordRequired(mockUserAttributes, mockRequiredAttributes); // 验证弹窗是否被正确打开 expect(component.openNewPasswordModal).toHaveBeenCalledWith(mockUserAttributes, mockRequiredAttributes); });
三、几个关键注意事项
- 绝对不要调用真实服务:所有Cognito相关的类和方法都要mock,保证测试的独立性和稳定性。
- 覆盖所有分支:除了成功/失败,还要考虑特殊回调(比如
newPasswordRequired、mfaRequired)的场景。 - 依赖注入的配置:如果你的组件是从
environment或注入的配置服务里拿UserPoolId/ClientId,记得在TestBed里提供模拟的配置。
内容的提问来源于stack exchange,提问作者Bhadra
相关产品推荐
相关产品推荐

