如何对导出对象使用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的是被测代码实际使用的对象引用。 - 如果
nativeWindowgetter返回的是动态创建的对象(非单例),记得每次测试前重新Spy,避免测试之间的干扰。 - 对于
fetch这类异步方法,可以用and.returnValue(Promise.resolve(mockResponse))模拟异步行为,再配合async/await或fakeAsync/tick处理测试中的异步逻辑。
内容的提问来源于stack exchange,提问作者Max Bösch
相关产品推荐
相关产品推荐

