You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jasmine Marbles测试时NGRX Effect未执行的排查求助

问题排查与修复方案

我来帮你梳理下导致Effect未运行、测试断言失败的几个关键问题:

1. 依赖注入拼写错误

这是最核心的问题:你在TestBed配置里把useValue写成了小写的usevalue,导致AuthService的Spy没有被正确注入到Effect中。Effect实际调用的不是你模拟的Spy,自然不会触发后续的动作流。

错误代码:

{ provide: AuthService, usevalue: { completeAuthentication: completeAuthSpy } }

修正后:

{ provide: AuthService, useValue: { completeAuthentication: completeAuthSpy } }

2. 测试变量初始化污染风险

你把actions$定义在了beforeEach外部,这会导致不同测试用例之间的状态污染。建议在每次测试前重新初始化actions$:

let actions$: Observable<Action>; // 仅声明类型
let completeAuthSpy: jasmine.Spy;
let userEffects: UserEffects;

beforeEach(() => {
  actions$ = new Observable<Action>(); // 每次测试重新初始化
  completeAuthSpy = jasmine.createSpy();
  // ... 其他TestBed配置
});

3. 时间线与Marble语法细节

你的Marble时间线逻辑是对的,但可以调整得更严谨:确保response的完成信号和expected的时间线完全匹配。另外,注意你创建的User对象中state设为了undefined,虽然不影响测试运行,但如果业务逻辑期望state有值,后续可能需要调整。

修正后的完整测试代码

import { UserEffects } from './user.effects';
import { AuthService } from './../../core/services/auth.service';
import { ApiServiceMock, ApplicationInsightServiceMock, AppSettingsServiceMock, AuthServiceMock, RouterMock, UserServiceMock } from './../../../testing-utils/mocks/service-mocks';
import { TestBed } from '@angular/core/testing';
import { Action } from '@ngrx/store';
import { provideMockActions } from '@ngrx/effects/testing';
import { Observable } from 'rxjs';
import * as userActions from '../actions/user.actions';
import { cold, hot } from 'jasmine-marbles';
import { User } from 'oidc-client';

let actions$: Observable<Action>;
let completeAuthSpy: jasmine.Spy;
let userEffects: UserEffects;

beforeEach(() => {
  actions$ = new Observable<Action>();
  completeAuthSpy = jasmine.createSpy();
  TestBed.configureTestingModule({
    providers: [
      provideMockActions(() => actions$),
      UserEffects,
      AppSettingsServiceMock,
      ApiServiceMock,
      UserServiceMock,
      RouterMock,
      ApplicationInsightServiceMock,
      { provide: AuthService, useValue: { completeAuthentication: completeAuthSpy } }
    ],
  });
  userEffects = TestBed.inject(UserEffects);
});

describe('UserEffects', () => {
  describe('CompleteAuthentication', () => {
    it('Should dispatch authenticationSuccess action on success', () => {
      const userState = new User({
        id_token: 'TestID',
        session_state: 'TestState',
        access_token: 'TestToken',
        refresh_token: 'TestRefreshToken',
        token_type: 'TestTokenType',
        scope: 'TestScope',
        profile: {} as any,
        expires_at: 6,
        state: 'test-user-state', // 可以设置一个具体值便于验证
      });
      const outcome = userActions.authenticationSuccess({ value: userState.state });
      const response = cold('-a|', { a: userState });
      const expected = cold('--b', { b: outcome });

      completeAuthSpy.and.returnValue(response.toPromise());
      actions$ = hot('-c', { c: userActions.completeAuthentication });

      expect(userEffects.compelteAuthentication$).toBeObservable(expected);
      expect(completeAuthSpy).toHaveBeenCalled();
    });
  });
});

额外提示

注意你的Effect属性名compelteAuthentication$存在拼写错误(少了一个字母l,正确应为completeAuthentication$),虽然当前测试能匹配,但建议统一修正,避免后续维护混淆。

内容的提问来源于stack exchange,提问作者Chirag Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:22:43