NgRx新手求助:如何测试带{dispatch: false}的Effect?
测试NgRx Effect中Service方法调用的解决方案
别担心,我来帮你搞定这个测试!针对你写的NotificationEffects,我们可以通过模拟依赖并触发对应Action,轻松验证notificationService.info是否被正确调用。下面是完整的测试代码和详细说明:
完整测试代码
import { TestBed } from '@angular/core/testing'; import { provideMockActions } from '@ngrx/effects/testing'; import { Observable, of } from 'rxjs'; import { NotificationEffects } from './notification.effects'; import * as notificationAction from './notification.actions'; import { NotificationService } from './notification.service'; import { cold } from 'jasmine-marbles'; describe('NotificationEffects', () => { let effects: NotificationEffects; let actions$: Observable<any>; let notificationServiceSpy: jasmine.SpyObj<NotificationService>; beforeEach(() => { // 创建NotificationService的模拟对象,监听info方法的调用 const spy = jasmine.createSpyObj('NotificationService', ['info']); TestBed.configureTestingModule({ providers: [ NotificationEffects, // 提供可手动控制的Action流 provideMockActions(() => actions$), // 用模拟对象替换真实的NotificationService { provide: NotificationService, useValue: spy } ] }); effects = TestBed.inject(NotificationEffects); notificationServiceSpy = TestBed.inject(NotificationService) as jasmine.SpyObj<NotificationService>; }); describe('notificationShow$', () => { it('should call notificationService.info with the payload config', () => { // 准备测试用的配置和Action const testConfig = { title: '测试通知', message: '这是一条测试消息' }; const action = new notificationAction.NotificationShowAction({ config: testConfig }); // 把Action注入到Effect的Action流中 actions$ = of(action); // 订阅Effect(因为这个Effect是dispatch: false,订阅后才会执行内部的do逻辑) effects.notificationShow$.subscribe(); // 验证info方法是否被正确调用,参数是否匹配 expect(notificationServiceSpy.info).toHaveBeenCalledWith(testConfig); }); // 如果你需要测试更复杂的流场景,可以用marbles测试方式 it('should handle NOTIFICATION_SHOW action via marbles', () => { const testConfig = { title: '测试通知', message: '这是一条测试消息' }; const action = new notificationAction.NotificationShowAction({ config: testConfig }); // 用cold marble模拟异步Action流 actions$ = cold('-a', { a: action }); effects.notificationShow$.subscribe(); expect(notificationServiceSpy.info).toHaveBeenCalledWith(testConfig); }); }); });
关键步骤拆解
- 模拟依赖:用
jasmine.createSpyObj生成NotificationService的模拟对象,这样我们可以全程监听info方法的调用状态。 - 配置测试环境:通过
provideMockActions提供可手动控制的Action流,同时将模拟的Service注入测试模块,替换真实服务。 - 触发Action:用
of(action)或marbles的cold方法生成Action流,让Effect能接收到目标Action。 - 执行Effect逻辑:因为你的Effect设置了
dispatch: false(不输出新Action),所以需要手动订阅它,才能触发内部的do操作。 - 验证调用结果:最后用Jasmine断言,检查
info方法是否被调用,并且传入的参数和我们预设的一致。
为什么之前的示例没帮到你?
很多通用示例会重点讲解有输出Action的Effect测试,而你的Effect属于dispatch: false类型,不需要验证输出Action,只需要聚焦于Service方法的调用验证——这也是你可能没找到直接解决方案的原因。
内容的提问来源于stack exchange,提问作者camden_kid
相关产品推荐
相关产品推荐

