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

如何用Jasmine单元测试验证授权成功后及链接点击的页面跳转?

Angular Jasmine路由跳转单元测试解决方案

问题说明

需要验证两个路由跳转场景:

  1. 点击页面中routerLink="/signup"的链接后跳转至/signup
  2. 调用登录接口授权成功后跳转至Lobby页面
    目前第一个场景的测试未得到预期结果。

解决方案

1. 修复点击routerLink跳转的测试

你的测试代码存在两个核心问题:

  • 未在测试模块中声明LoginComponent,导致组件无法正确初始化
  • 未处理路由跳转的异步操作,需要在fakeAsync中调用tick()触发路由完成跳转

修复后的测试代码:

import { fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { LobbyComponent } from '../lobby/lobby.component';
import { SignupComponent } from '../signup/signup.component';
import { routes } from '../../app-routing.module';
import { FormBuilder, MatSnackBar, Overlay } from '@angular/material';

describe('Router redirects to proper pages', () => {
  let fixture: ComponentFixture<LoginComponent>;
  let redirectLink: HTMLElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule.withRoutes(routes),
        HttpClientTestingModule,
      ],
      declarations: [LoginComponent, LobbyComponent, SignupComponent],
      providers: [FormBuilder, MatSnackBar, Overlay],
    });

    fixture = TestBed.createComponent(LoginComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement;
    redirectLink = compiled.query(By.css('[routerLink="/signup"]')).nativeElement;
  });

  it('should redirect to /signup when clicking the signup link', fakeAsync(() => {
    redirectLink.click();
    tick();
    fixture.detectChanges();
    expect(TestBed.inject(Router).url).toEqual('/signup');
  }));
});

2. 实现授权成功后的跳转测试

需要模拟登录接口返回成功响应,验证AuthService是否触发路由跳转至Lobby:

import { fakeAsync, tick } from '@angular/core/testing';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { AuthService } from '../../auth.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { environment } from '../../environments/environment';
import { BackendRoutes } from '../../constants/backend-routes';
import { Paths } from '../../constants/paths';
import { Router } from '@angular/router';
import { FormBuilder } from '@angular/forms';
import { PushNotificationService } from 'src/app/push-notification.service';

describe('LoginComponent - Authorization Success Redirect', () => {
  let fixture: ComponentFixture<LoginComponent>;
  let authService: AuthService;
  let httpMock: HttpTestingController;
  let router: Router;
  let component: LoginComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [LoginComponent],
      providers: [
        AuthService,
        FormBuilder,
        { provide: PushNotificationService, useValue: { createNotification: jasmine.createSpy() } }
      ]
    });

    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    authService = TestBed.inject(AuthService);
    httpMock = TestBed.inject(HttpTestingController);
    router = TestBed.inject(Router);
    spyOn(router, 'navigate');
    fixture.detectChanges();
  });

  it('should redirect to Lobby after successful authorization', fakeAsync(() => {
    // 设置表单为有效状态
    component.form.patchValue({
      username: 'testuser',
      password: 'testpass123'
    });

    // 调用登录方法
    component.userLoginClick();

    // 拦截并返回成功的登录响应
    const req = httpMock.expectOne(`${environment.domain}${BackendRoutes.Login}`);
    expect(req.request.method).toBe('POST');
    req.flush({ success: true, token: 'fake-token', user: {} });

    tick();

    // 验证是否调用了路由跳转
    expect(router.navigate).toHaveBeenCalledWith([`/${Paths.Lobby}`]);
    httpMock.verify();
  }));
});

关键注意事项

  • 测试路由跳转时,必须在fakeAsync中使用tick()处理异步操作
  • 组件测试时,确保测试模块中声明了所有需要的组件和服务
  • 对于依赖外部服务的逻辑,优先使用mock或spy来隔离依赖,避免真实请求影响测试结果

内容的提问来源于stack exchange,提问作者Vova Aleshchenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:10:29