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

如何对导出对象使用toHaveBeenCalledWith?Karma/Jasmine支持吗?

当然可行!在Karma/Jasmine中完全可以检查对导出对象(或服务提供的nativeWindow这类对象)的方法调用,我来给你一步步讲怎么实现:

核心思路

你需要先获取到提供nativeWindow的服务实例,然后要么直接SpyOn该实例返回的nativeWindow上的目标方法,要么mock整个nativeWindow对象,来更可控地完成测试验证。

具体实现步骤

假设你的服务叫WindowService,结构如下:

@Injectable({ providedIn: 'root' })
export class WindowService {
  get nativeWindow(): any {
    return window;
  }
}

方法1:直接SpyOn真实nativeWindow的方法

这种方式适合你不需要修改方法返回值,只是想验证调用场景的情况:

import { TestBed } from '@angular/core/testing';
import { WindowService } from './window.service';
import { YourTestedCode } from './your-tested-code';

describe('YourTestedCode', () => {
  let windowService: WindowService;
  let testedCode: YourTestedCode;
  let nativeWindowOpenSpy: jasmine.Spy;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [WindowService, YourTestedCode]
    });

    windowService = TestBed.inject(WindowService);
    testedCode = TestBed.inject(YourTestedCode);
    // SpyOn nativeWindow上的open方法,callThrough会保留原方法逻辑,也可以用returnValue模拟返回
    nativeWindowOpenSpy = spyOn(windowService.nativeWindow, 'open').and.callThrough();
  });

  it('should call nativeWindow.open with correct URL', () => {
    // 执行被测代码里触发调用的逻辑
    testedCode.openExternalLink('https://example.com');

    // 验证调用细节
    expect(nativeWindowOpenSpy).toHaveBeenCalledWith('https://example.com');
    expect(nativeWindowOpenSpy).toHaveBeenCalledTimes(1);
  });
});

方法2:Mock整个nativeWindow对象(更安全,避免污染真实window)

如果不想影响真实的浏览器window对象,或者需要自定义方法的返回值/行为,推荐这种方式:

import { TestBed } from '@angular/core/testing';
import { WindowService } from './window.service';
import { YourTestedCode } from './your-tested-code';

describe('YourTestedCode', () => {
  let windowService: WindowService;
  let testedCode: YourTestedCode;
  // 自定义mock对象,包含你需要测试的所有方法
  const mockNativeWindow = {
    open: jasmine.createSpy('open').and.returnValue({ closed: false } as Window),
    alert: jasmine.createSpy('alert')
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [WindowService, YourTestedCode]
    });

    windowService = TestBed.inject(WindowService);
    testedCode = TestBed.inject(YourTestedCode);
    // SpyOn nativeWindow的getter,返回我们的mock对象
    spyOnProperty(windowService, 'nativeWindow').and.returnValue(mockNativeWindow);
  });

  it('should trigger nativeWindow.open with correct parameters', () => {
    testedCode.openExternalLink('https://example.com', '_blank');

    expect(mockNativeWindow.open).toHaveBeenCalledWith('https://example.com', '_blank');
  });

  it('should show alert on error', () => {
    testedCode.handleError('Something went wrong');

    expect(mockNativeWindow.alert).toHaveBeenCalledWith('Something went wrong');
  });
});

关键注意点

  • 一定要通过你的服务实例来访问nativeWindow,而不是直接用全局window——这样才能确保你Spy的是被测代码实际使用的对象引用。
  • 如果nativeWindow getter返回的是动态创建的对象(非单例),记得每次测试前重新Spy,避免测试之间的干扰。
  • 对于fetch这类异步方法,可以用and.returnValue(Promise.resolve(mockResponse))模拟异步行为,再配合async/await或fakeAsync/tick处理测试中的异步逻辑。

内容的提问来源于stack exchange,提问作者Max Bösch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:25:41