Angular组件构造函数中window.opener条件逻辑的单元测试方案咨询
如何测试Angular组件中依赖window.opener的构造函数逻辑?
你的核心问题是构造函数在初始化时直接访问全局window.opener,导致测试时无法提前拦截这个属性。不需要新增测试文件,也不需要从其他组件调用,只需在现有测试文件中通过重置全局window属性的方式,分别覆盖三种场景即可:
前置准备:重置全局window状态
由于window是全局共享对象,为了避免测试用例互相干扰,需要在每个测试前后保存并恢复原始的window.opener值:
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NavbarComponent } from './navbar.component'; import { NavbarService } from './navbar.service'; let originalOpener: Window | null; beforeEach(() => { // 保存原始opener状态 originalOpener = window.opener; TestBed.configureTestingModule({ declarations: [NavbarComponent], providers: [NavbarService] }); }); afterEach(() => { // 恢复原始opener状态 window.opener = originalOpener; });
测试场景1:当window.opener存在时的行为
模拟组件被其他页面打开的情况,验证导航隐藏、noOpener赋值逻辑:
it('被其他页面打开时,隐藏弹出链接并调用nav.hide()', () => { // 提前设置window.opener为非空值 window.opener = {} as Window; // 监听NavbarService的hide方法 const navService = TestBed.inject(NavbarService); const hideSpy = spyOn(navService, 'hide'); // 创建组件(构造函数会立即执行) const fixture = TestBed.createComponent(NavbarComponent); const component = fixture.componentInstance; // 断言逻辑是否符合预期 expect(component.noOpener).toBe(false); expect(hideSpy).toHaveBeenCalled(); });
测试场景2:当window.opener不存在时的行为
模拟组件作为独立页面打开的情况,验证导航显示、noOpener赋值逻辑:
it('作为独立页面打开时,显示弹出链接', () => { // 确保window.opener为null window.opener = null; const navService = TestBed.inject(NavbarService); const hideSpy = spyOn(navService, 'hide'); const fixture = TestBed.createComponent(NavbarComponent); const component = fixture.componentInstance; expect(component.noOpener).toBe(true); expect(hideSpy).not.toHaveBeenCalled(); });
测试场景3:访问window.opener抛出异常时的行为
模拟跨域等场景下访问window.opener抛出错误的情况,验证异常捕获逻辑:
it('访问window.opener抛出异常时,隐藏导航并记录错误', () => { // 模拟访问opener时抛出错误 Object.defineProperty(window, 'opener', { get: () => { throw new Error('Security restriction'); }, configurable: true // 允许后续重置 }); const navService = TestBed.inject(NavbarService); const hideSpy = spyOn(navService, 'hide'); const consoleErrorSpy = spyOn(console, 'error'); const fixture = TestBed.createComponent(NavbarComponent); const component = fixture.componentInstance; expect(component.noOpener).toBe(false); expect(hideSpy).toHaveBeenCalled(); expect(consoleErrorSpy).toHaveBeenCalled(); });
为什么之前的测试无效?
你之前尝试spyOn(window, 'open')是方向错误——你的代码逻辑依赖的是window.opener(判断当前页面是否被其他窗口打开),而不是window.open(打开新窗口的方法),所以这个spy完全没作用。
内容的提问来源于stack exchange,提问作者JoSSte
相关产品推荐
相关产品推荐

