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

NGXS的Actions Observable做Jest测试时断言失败超时无报错问题

问题原因

这个问题不是NGXS的已知缺陷,是RxJS Observable的默认行为导致的:当Observable的next回调中抛出未捕获的异常时,异常会被Observable内部捕获并进入错误处理通道,既不会向上抛到测试运行器的全局上下文,也不会继续执行回调中后续的done()调用。测试框架既收不到断言失败的信号,也等不到测试结束的回调通知,最终就会触发超时。
你之前用Subject做对照测试表现正常,大概率是因为你的测试用例中没有给Subject的订阅配置错误回调,异常会被RxJS抛到全局的未处理错误事件,被测试框架捕获到了。

解决方案

方案1:补充订阅的错误回调

给subscribe方法传入完整的观察者对象,在错误回调中把异常传递给done,测试框架就能正常捕获到断言失败:

it('should example', (done) => {
  actions$
    .pipe(ofActionCompleted(ExampleAction))
    .subscribe({
      next: () => {
        console.log('i was here! Before');
        expect(true).toBeFalsy();
        console.log('i was here! After');
        done();
      },
      error: (err) => done(err) // 捕获回调内的所有异常,传递给测试框架
    });

  store.dispatch(new ExampleAction());
});

方案2:改用async/await写法(更推荐)

把Observable转成Promise,用async/await的同步写法编写测试,不需要手动处理done回调和错误捕获,断言抛出的异常会自动被测试框架识别。如果使用RxJS 6版本可以直接调用toPromise()方法,RxJS 7+可以用firstValueFrom:

import { take } from 'rxjs';

// 省略测试套件其他代码
it('should example', async () => {
  const actionCompletePromise = actions$.pipe(ofActionCompleted(ExampleAction), take(1)).toPromise();

  store.dispatch(new ExampleAction());
  await actionCompletePromise;

  // 直接写断言即可,失败会自动抛出
  expect(true).toBeFalsy();
});

方案3:直接监听dispatch返回的Observable

NGXS的store.dispatch方法本身就会返回一个Action执行完成后触发的Observable,不需要额外监听全局的Actions流,写法更简洁:

it('should example', async () => {
  await store.dispatch(new ExampleAction()).toPromise();
  expect(true).toBeFalsy();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:15:04