当返回实际上是 EMPTY 可观察值时,如何使用大理石方法进行测试?

Tab*_*res 5 javascript jasmine rxjs5 ngrx-effects rxjs-marbles

我使用 rxjs 中的 EMPTY 来处理 catchError,为了通过失败场景,预期的正确值是多少。

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
  ) {}
}


Run Code Online (Sandbox Code Playgroud)
// 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);

})
Run Code Online (Sandbox Code Playgroud)

Sco*_*ott 3

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

EMPTYorempty()本身将匹配cold('|')or hot('|')。请阅读下文了解其匹配cold('')hot('')效果的原因。(请参阅本 RxJS 文档的示例部分,其中也显示了这一点。)

通过另一个问题的类似答案证实,现在引用原因:

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

因此,虽然EMPTY(或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);

})
Run Code Online (Sandbox Code Playgroud)

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

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('|'));
});
Run Code Online (Sandbox Code Playgroud)