如何测试Angular服务构造函数中chrome.tabs.onUpdated.addListener功能
测试ChromeService的页面URL变化检测逻辑
原服务代码
export class ChromeService { private newTabValue$ = new Subject<{ tabId: number; url: string }>(); constructor() { chrome.tabs.onUpdated.addListener((tabId: number, changeInfo: TabChangeInfo, tab: Tab) => { if (changeInfo.status === 'complete') { if (tab.url !== undefined) { this.newTabValue$.next({ tabId: tabId, url: tab.url }); } } }); } }
测试方案与代码
要测试这个服务,核心是模拟chrome.tabs.onUpdated的回调触发,并验证newTabValue$的输出是否符合预期。以下是基于Jasmine+Karma的测试用例:
import { ChromeService } from './chrome.service'; import { Subject } from 'rxjs'; // 定义类型避免测试时类型报错 interface TabChangeInfo { status?: string; } interface Tab { url?: string; } describe('ChromeService', () => { let service: ChromeService; let mockTabsOnUpdated: { addListener: jasmine.Spy }; let emittedValue: { tabId: number; url: string } | undefined; beforeEach(() => { // 模拟chrome.tabs.onUpdated对象,保存服务注册的回调函数 mockTabsOnUpdated = { addListener: jasmine.createSpy('addListener').and.callFake((callback) => { (mockTabsOnUpdated as any).callback = callback; }) }; // 将模拟对象挂载到全局window (window as any).chrome = { tabs: { onUpdated: mockTabsOnUpdated } }; // 初始化服务实例 service = new ChromeService(); // 订阅私有Subject,捕获发射的值 service['newTabValue$'].subscribe(value => { emittedValue = value; }); }); afterEach(() => { // 清理全局模拟对象,避免测试污染 delete (window as any).chrome; emittedValue = undefined; }); it('当页面加载完成且存在URL时,应发射正确的tabId和url', () => { const testTabId = 123; const testUrl = 'https://example.com'; const changeInfo = { status: 'complete' }; const tab = { url: testUrl }; // 手动触发回调函数 (mockTabsOnUpdated as any).callback(testTabId, changeInfo, tab); expect(emittedValue).toEqual({ tabId: testTabId, url: testUrl }); }); it('当页面状态不是complete时,不应发射值', () => { const testTabId = 123; const changeInfo = { status: 'loading' }; const tab = { url: 'https://example.com' }; (mockTabsOnUpdated as any).callback(testTabId, changeInfo, tab); expect(emittedValue).toBeUndefined(); }); it('当tab.url为undefined时,不应发射值', () => { const testTabId = 123; const changeInfo = { status: 'complete' }; const tab = { url: undefined }; (mockTabsOnUpdated as any).callback(testTabId, changeInfo, tab); expect(emittedValue).toBeUndefined(); }); });
关键说明
- 模拟Chrome API:测试环境没有真实的chrome对象,因此手动模拟
chrome.tabs.onUpdated,并通过Spy保存服务注册的回调函数,方便后续主动触发测试。 - 捕获私有Subject输出:通过
service['newTabValue$']访问私有Subject(若追求更规范的写法,可给服务添加公共的Observable getter,比如get tabUpdate$() { return this.newTabValue$.asObservable(); })。 - 覆盖核心场景:测试了正常触发、状态不满足、URL缺失三种情况,确保服务逻辑的正确性。
内容的提问来源于stack exchange,提问作者Nisanio
相关产品推荐
相关产品推荐

