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

Angular中如何用Jasmine+Karma测试window.location.href并阻止测试跳转

修复方案(无需修改业务代码)

你遇到的两个问题本质都是测试时直接操作了原生window.location.href导致的,只需要在测试用例中拦截href的赋值操作即可同时解决跳转和断言错误的问题:
修改a.component.spec.ts中的测试用例代码:

it('test redirect function', () => {
  // 监听window.location.href的set操作,stub方法会拦截原生赋值行为,避免页面跳转
  const hrefSetSpy = spyOnProperty(window.location, 'href', 'set').and.stub();

  component.redirect();

  // 校验spy是否接收到了预期的URL参数
  expect(hrefSetSpy).toHaveBeenCalledWith('https://sample.com');
});

这个方案的原理是利用Jasmine的spyOnProperty监听href属性的setter,and.stub()会拦截原生的赋值逻辑,不会真的修改浏览器地址,自然也不会触发跳转,同时可以通过校验spy的调用参数来确认赋值是否符合预期。

提示:如果部分浏览器环境下因安全限制无法spy原生window.location.href的setter,直接使用下面的优化方案即可。


更易测试的优化方案

如果后续有调整需求,推荐用Angular依赖注入封装全局window对象,完全避免测试时污染全局环境:

1. 定义全局Window注入令牌

新增src/app/tokens/window.token.ts:

import { InjectionToken, FactoryProvider } from '@angular/core';

export const WINDOW = new InjectionToken<Window>('WindowToken');

export function windowFactory(): Window {
  return window;
}

export const WINDOW_PROVIDER: FactoryProvider = {
  provide: WINDOW,
  useFactory: windowFactory
};

2. 模块中注册提供者

在你的功能模块或者根模块的providers数组中加入WINDOW_PROVIDER。

3. 改造业务组件

修改a.component.ts:

import { Component, OnInit, Inject } from '@angular/core';
import { Service } from 'services/service';
import { WINDOW } from 'src/app/tokens/window.token';

@Component({
  selector: 'a',
  templateUrl: './a.component.html',
  styleUrls: ['./a.component.scss']
})
export class AComponent implements OnInit {
  constructor(
    private service: Service,
    @Inject(WINDOW) private window: Window
  ) {}

  ngOnInit(): void {}

  redirect() {
    this.window.location.href = 'https://sample.com'
  }
}

4. 改造测试用例

修改a.component.spec.ts的测试配置,直接注入mock的window对象:

describe('#AComponent', () => {
  let component: AComponent;
  let fixture: ComponentFixture<AComponent>;
  // 定义mock window对象
  const mockWindow = { location: { href: '' } };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule],
      declarations: [AComponent],
      // 用mock对象替换原生window
      providers: [{ provide: WINDOW, useValue: mockWindow }]
    }).compileComponents();
  }));

  // 其余基础配置保持不变

  it('test redirect function', () => {
    component.redirect();
    // 直接校验mock对象的属性即可
    expect(mockWindow.location.href).toEqual('https://sample.com');
  });
});

这个方案完全不会触及全局原生window对象,从根源上避免了测试时触发页面跳转的问题,也更符合Angular的依赖注入设计规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 10:39:03