首页 > 解决方案 > How to test with the marble approach when the returm is a EMPTY observable in effect?

问题描述

I am using EMPTY from rxjs in order to handle the catchError, What is the correct value for expected in order to pass the fail scenario.

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { EMPTY } from 'rxjs';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { MoviesService } from './movies.service';

@Injectable()
export class MovieEffects {

  loadMovies$ = createEffect(() => this.actions$.pipe(
    ofType('[Movies Page] Load Movies'),
    mergeMap(() => this.moviesService.getAll()
      .pipe(
        map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
        catchError(() => EMPTY)
      ))
    )
  );

  constructor(
    private actions$: Actions,
    private moviesService: MoviesService
  ) {}
}


// unit test

it('should return a empty observable', () => {
   this.moviesServiceSpy.and.return(throwError('Error in service'));

   action$ = hot('a', a: { loadMovies() });

   const expected = cold('|');

   expect(loadMovies$).toBeObservable(expected);

})

标签: javascriptjasminerxjs5ngrx-effectsrxjs-marbles

解决方案


我自己遇到了这个问题,偶然发现了你的问题。我想我有一个答案:因为EMPTY 立即完成,我认为它意味着 0 时间过去了。(编辑:这是错误的!)

EMPTYorempty()本身将匹配cold('|')or hot('|')。请阅读以下内容,了解它为何匹配cold('')hot('')生效。(请参阅此 RxJS 文档的示例部分,其中也显示了这一点。)

由另一个问题的类似答案确认,现在引用原因:

中的管道字符cold('|')表示可观察流的完成。但是,您的效果不会完成。empty()observable 确实完成了,但从只看到 observable 合并到效果 observable 的流中返回-empty()switchMap没有完成效果 observable。

因此,虽然EMPTY(or empty()) 被记录为立即完成,但在效果中使用它的最终结果表明效果永远不会完成。

将此答案插入您的示例:

it('should return a empty observable', () => {
   this.moviesServiceSpy.and.return(throwError('Error in service'));

   action$ = hot('a', a: { loadMovies() });

   const expected = cold('');

   expect(loadMovies$).toBeObservable(expected);

})

只是为了好玩,以下测试也通过了:

it('should match EMPTY with a single tick pipe marble', () => {
   expect(EMPTY).toBeObservable(cold('|'));
   expect(EMPTY).toBeObservable(hot('|'));

   // empty() is deprecated, but these assertions still pass.
   expect(empty()).toBeObservable(cold('|'));
   expect(empty()).toBeObservable(hot('|'));
});

推荐阅读