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

如何使用Jasmine为Angular密码验证组件编写全覆盖spec.ts测试代码

完整Jasmine测试代码(覆盖所有语句分支)

以下测试对所有外部依赖(路由、AWS Auth、系统弹窗)做了模拟,不会调用真实服务,直接替换你的spec.ts内容即可运行:

import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { Router, ActivatedRoute } from '@angular/router';
import { Auth } from '@aws-amplify/auth';
import { CodigoVerificacionClaveComponent } from './codigo-verificacion-clave.component';

describe('CodigoVerificacionClaveComponent', () => {
  let component: CodigoVerificacionClaveComponent;
  let fixture: ComponentFixture<CodigoVerificacionClaveComponent>;
  let router: Router;
  let route: ActivatedRoute;
  const mockTestEmail = 'test@example.com';

  // 全局模拟系统alert弹窗,避免测试时弹出窗口
  beforeAll(() => {
    spyOn(window, 'alert');
  });

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ CodigoVerificacionClaveComponent ],
      providers: [
        // 模拟ActivatedRoute,返回测试用的邮箱参数
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get: jasmine.createSpy('get').and.returnValue(mockTestEmail)
              }
            }
          }
        },
        // 模拟Router,监听跳转动作
        {
          provide: Router,
          useValue: {
            navigate: jasmine.createSpy('navigate')
          }
        }
      ]
    })
    .compileComponents();

    router = TestBed.inject(Router);
    route = TestBed.inject(ActivatedRoute);
    // 模拟AWS Auth的两个方法,避免调用真实接口
    spyOn(Auth, 'signIn').and.stub();
    spyOn(Auth, 'completeNewPassword').and.stub();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(CodigoVerificacionClaveComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('初始化时从路由参数正确获取邮箱', () => {
    expect(route.snapshot.paramMap.get).toHaveBeenCalledWith('param');
    expect(component.currentemail).toBe(mockTestEmail);
  });

  it('登录失败时弹出认证失败提示', fakeAsync(async () => {
    (Auth.signIn as jasmine.Spy).and.returnValue(Promise.reject(new Error('登录失败')));
    component.currentpassword = 'testpwd123';

    await component.changePasswordCognito();
    tick();

    expect(Auth.signIn).toHaveBeenCalledWith(mockTestEmail, 'testpwd123');
    expect(window.alert).toHaveBeenCalledWith('User Authentication failed!');
  }));

  it('需重置密码且重置成功时跳转首页', fakeAsync(async () => {
    const mockUser = {
      challengeName: 'NEW_PASSWORD_REQUIRED',
      challengeParam: { requiredAttributes: [] }
    };
    (Auth.signIn as jasmine.Spy).and.returnValue(Promise.resolve(mockUser));
    (Auth.completeNewPassword as jasmine.Spy).and.returnValue(Promise.resolve({}));
    component.currentpassword = 'oldpwd';
    component.newpasswordchange = 'newpwd123';

    await component.changePasswordCognito();
    tick();

    expect(Auth.completeNewPassword).toHaveBeenCalledWith(mockUser, 'newpwd123');
    expect(window.alert).toHaveBeenCalledWith('El cambio de contraseña ha sido satisfactorio!!!, You are logged in successfully!');
    expect(router.navigate).toHaveBeenCalledWith(['/home-express']);
  }));

  it('需重置密码但重置失败时打印错误日志', fakeAsync(async () => {
    const mockUser = {
      challengeName: 'NEW_PASSWORD_REQUIRED',
      challengeParam: { requiredAttributes: [] }
    };
    const mockError = new Error('重置密码失败');
    (Auth.signIn as jasmine.Spy).and.returnValue(Promise.resolve(mockUser));
    (Auth.completeNewPassword as jasmine.Spy).and.returnValue(Promise.reject(mockError));
    const consoleSpy = spyOn(console, 'log');
    component.currentpassword = 'oldpwd';
    component.newpasswordchange = 'newpwd123';

    await component.changePasswordCognito();
    tick();

    expect(consoleSpy).toHaveBeenCalledWith(mockError);
    consoleSpy.calls.reset();
  }));

  it('无需重置密码且登录成功时跳转首页', fakeAsync(async () => {
    const mockUser = {
      challengeName: 'OTHER_CHALLENGE',
      signInUserSession: { accessToken: 'mock_token' }
    };
    (Auth.signIn as jasmine.Spy).and.returnValue(Promise.resolve(mockUser));
    component.currentpassword = 'testpwd123';

    await component.changePasswordCognito();
    tick();

    expect(window.alert).toHaveBeenCalledWith('You are logged in successfully!');
    expect(router.navigate).toHaveBeenCalledWith(['/home-express']);
  }));

  it('无需重置密码但token为空时提示认证失败', fakeAsync(async () => {
    const mockUser = {
      challengeName: 'OTHER_CHALLENGE',
      signInUserSession: null
    };
    (Auth.signIn as jasmine.Spy).and.returnValue(Promise.resolve(mockUser));
    component.currentpassword = 'testpwd123';

    await component.changePasswordCognito();
    tick();

    expect(window.alert).toHaveBeenCalledWith('User Authentication failed!');
  }));
});

覆盖说明

所有逻辑分支全部覆盖:

  • 组件初始化读取路由参数逻辑
  • 登录抛出错误分支
  • 需重置密码的成功、失败分支
  • 无需重置密码的登录成功、登录失败分支

内容的提问来源于stack exchange,提问作者Cristopher Caceres

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:39:02