Angular @ngrx/effects单元测试:Action未清除问题排查与解决
问题原因分析
你遇到的问题核心在于测试用例间的状态污染:
- 你在
describe顶层定义了共享的action$变量,所有测试用例复用同一个引用。第一个测试将action$替换为of(...)创建的Observable,而provideMockActions传入的工厂函数始终指向这个共享变量。 - Effects模块初始化时会持续订阅
action$,而of创建的是冷Observable——每次有新订阅时,它都会重新发射所有内部值。后续测试执行时,新创建的Effects实例会再次订阅这个未被重置的action$,导致之前的abortaction被重复触发。 - 加上你给
abort$Effect设置了dispatch: false,它不会触发新的action,但自身的订阅不会自动终止,进一步加剧了跨测试的状态残留。
解决方法
1. 用Subject替代静态Observable,每个测试独立控制action发射
把action$改为Subject<Action>,并移到beforeEach中初始化,确保每个测试用例都有独立的action流:
describe('MyBankEffects', () => { let effects: MyBankEffects; let action$: Subject<Action>; beforeEach( () => { action$ = new Subject<Action>(); // 每个测试初始化新的Subject TestBed.configureTestingModule({ imports: [ EffectsModule.forFeature(MyBankEffects) ], providers: [ provideMockActions( () => action$), ] }); effects = TestBed.inject(MyBankEffects); }); // 每个测试结束后完成Subject,清理订阅 afterEach(() => { action$.complete(); }); it('should navigate to abort', (done) => { // 用next发射action,而非重新赋值action$ action$.next(myActions.abort({ reason: AbortReason.TIMEOUT })); effects.abort$.pipe(take(1)).subscribe({ next: () => { expect(...); }, error: e => done.fail(e), complete: () => { expect(...); done(); } }); }); });
2. 避免共享变量,每个测试重新初始化action$
如果你不想用Subject,也可以在beforeEach中每次创建新的空Observable,测试用例中再替换为对应action流(这种方式灵活性较低,仅作补充):
describe('MyBankEffects', () => { let effects: MyBankEffects; let action$: Observable<Action>; beforeEach( () => { action$ = EMPTY; // 初始化为空Observable TestBed.configureTestingModule({ imports: [ EffectsModule.forFeature(MyBankEffects) ], providers: [ provideMockActions( () => action$), ] }); effects = TestBed.inject(MyBankEffects); }); it('should navigate to abort', (done) => { action$ = of(myActions.abort({ reason: AbortReason.TIMEOUT })); effects.abort$.pipe(take(1)).subscribe({ // ... 订阅逻辑 }); }); });
关键注意点
- 不要在
describe顶层定义会被修改的测试变量,否则必然导致测试用例间的状态污染。 - 使用
Subject可以精准控制action的发射、完成时机,是测试NgRx Effects的标准做法。 - 每个测试结束后调用
action$.complete(),可以终止所有相关订阅,彻底清理状态。
内容的提问来源于stack exchange,提问作者Hilbert
相关产品推荐
相关产品推荐

