如何编写单元测试捕获NgRx Effect误加{dispatch:false}的配置错误
NgRx Effect
dispatch: false 配置错误的测试解决方案 问题根因
原有单元测试直接订阅了Effect实例对应的内部Observable,而dispatch: false配置仅会在NgRx Effects运行时层拦截返回的Action,阻止其派发到全局Action流,不会影响Effect内部流的正常输出,因此原有测试无法捕获该配置错误。
可选解决方案
方案1:直接断言Effect的配置属性
NgRx的
createEffect会将传入的配置项直接挂载到生成的Effect实例上,只需新增一条简单的断言用例即可覆盖配置校验:it('should enable dispatch for loadProducts$ effect', () => { // 直接校验Effect的dispatch配置为true expect(effects.loadProducts$.dispatch).toBeTrue(); });该方案实现成本极低,适合快速补全配置类校验场景。
方案2:模拟真实运行流程校验全局Action流
基于NgRx官方测试工具模拟线上真实运行逻辑,监听全局Action流判断返回的Action是否被正常派发,测试逻辑更贴近实际运行场景:
import { ActionsSubject, ofType } from '@ngrx/store'; import { provideMockEffects } from '@ngrx/effects/testing'; describe('loadProducts$', () => { let actionsSubject: ActionsSubject; let effects: ProductsEffects; let mockService: jasmine.SpyObj<ProductsService>; beforeEach(() => { mockService = jasmine.createSpyObj('ProductsService', ['load']); mockService.load.and.returnValue(of([{ id: 1, name: 'asd', price: '2', image: 2 }])); TestBed.configureTestingModule({ providers: [ provideMockEffects([ProductsEffects]), { provide: ProductsService, useValue: mockService } ] }); actionsSubject = TestBed.inject(ActionsSubject); effects = TestBed.inject(ProductsEffects); }); it('should dispatch loadProducts action after requestLoadProducts', (done) => { // 监听全局Action流,判断目标Action是否被正常派发 actionsSubject.pipe(ofType(loadProducts)).subscribe((action) => { expect(action.products).toEqual([{ id: 1, name: 'asd', price: '2', image: 2 }]); done(); }); // 触发初始Action actionsSubject.next(requestLoadProducts()); }); });如果Effect配置了
dispatch: false,返回的Action不会被派发到全局Action流,测试会超时失败,可精准捕获该类错误。方案3:静态规则前置拦截
接入
@ngrx/eslint-plugin的官方校验规则,在编码阶段直接拦截错误配置,无需到测试阶段才发现:启用
@ngrx/effects/no-useless-effect-config规则后,若Effect内部返回了Action但配置了dispatch: false,ESLint会直接抛出错误提示,从编码源头避免这类低级错误。
内容的提问来源于stack exchange,提问作者gr4viton
相关产品推荐
相关产品推荐

