如何为NgRX Store选择器单元测试实现测试覆盖率?
NgRX选择器Jest测试覆盖率问题解决方案
一、正确Mock getAllValidAddresses选择器
别再手动给this.isNIAddress$赋值了,用NgRX官方测试工具mock Store和选择器,让组件自己在ngOnInit里走正常逻辑,这样才能覆盖到选择器的调用:
导入测试依赖
从@ngrx/store/testing导入provideMockStore和MockStore,同时引入你的getAllValidAddresses选择器。配置TestBed提供Mock Store
在测试初始化阶段,用provideMockStore配置Store,直接给目标选择器指定返回值:import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { getAllValidAddresses } from './your-selector-path'; describe('YourComponent', () => { let component: YourComponent; let fixture: ComponentFixture<YourComponent>; let store: MockStore; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [YourComponent], // 独立组件写法,非独立组件用declarations providers: [ provideMockStore({ selectors: [ { selector: getAllValidAddresses, value: [{ postcode: 'BT1 1AA', valid: true }] // 模拟北爱地址数据 } ] }) ] }).compileComponents(); store = TestBed.inject(MockStore); fixture = TestBed.createComponent(YourComponent); component = fixture.componentInstance; });动态切换选择器返回值
如果不同测试用例需要不同的地址数据,用overrideSelector更新,再调用refreshState让组件感知状态变化:it('should set isNIAddress$ to true when NI address exists', () => { store.overrideSelector(getAllValidAddresses, [{ postcode: 'BT2 2BB' }]); store.refreshState(); component.ngOnInit(); fixture.detectChanges(); component.isNIAddress$.subscribe(isNI => { expect(isNI).toBe(true); }); });
二、解决component.ngOnInit()调用报错问题
报错大多是因为Store mock不完整,或者重复触发初始化逻辑,按以下方式排查:
- 避免重复触发ngOnInit:
fixture.detectChanges()会自动调用ngOnInit,如果要手动控制,创建组件后别先调用detectChanges,配置好mock后再手动调用component.ngOnInit(),最后执行detectChanges。 - 检查依赖完整性:确保组件所有依赖的服务都已在TestBed中提供或mock,漏依赖会导致初始化报错。
- 匹配组件逻辑的数据格式:mock的地址数据要和组件中
isNIAddress$的映射逻辑匹配,比如组件用邮编前缀判断北爱地址,mock数据就得带对应格式的邮编。
三、获取选择器的测试覆盖率
要让选择器代码被覆盖,核心是让组件实际调用选择器:
- 通过上述mock方式,组件在
ngOnInit中执行store.select(getAllValidAddresses),选择器代码会被执行,自然计入覆盖率。 - 若要单独覆盖选择器本身,可写独立的选择器测试用例:
import { getAllValidAddresses } from './your-selector-path'; import { AppState } from './your-state-path'; describe('getAllValidAddresses Selector', () => { it('should return only valid addresses', () => { const mockState: AppState = { addresses: { list: [{ id: 1, valid: true }, { id: 2, valid: false }] } }; expect(getAllValidAddresses(mockState)).toEqual([{ id: 1, valid: true }]); }); });
内容的提问来源于stack exchange,提问作者Bwizard
相关产品推荐
相关产品推荐

