【问题标题】:How to unit test ngrx effects when the API fail?API失败时如何对ngrx效果进行单元测试?
【发布时间】:2021-06-26 10:53:40
【问题描述】:

我可以对 ConfirmedMarkBookAsFinished 操作进行测试,但我不知道如何测试 failedMarkBookAsFinished。请帮忙测试一下。

这是 effect.ts 文件

markBookAsRead$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ReadingListActions.markBookAsFinished),
      concatMap(({ item }) => {
        return this.http
          .put<ReadingListItem>(
            `/api/reading-list/${item.bookId}/finished`,
            item
          )
          .pipe(
            map((data) =>
              ReadingListActions.confirmedMarkBookAsFinished({ item: data })
            ),
            catchError(() =>
              of(ReadingListActions.failedMarkBookAsFinished({ item }))
            )
          );
      })
    )
  );

所以基本上,我必须为效果成功和失败编写一个测试,我为成功编写了一个测试但是对于失败如何编写我不知道它

这是 effect.spec.ts 文件

import { TestBed } from '@angular/core/testing';
import { ReplaySubject } from 'rxjs';
import { provideMockActions } from '@ngrx/effects/testing';
import { provideMockStore } from '@ngrx/store/testing';
import { HttpTestingController } from '@angular/common/http/testing';

import { SharedTestingModule,createReadingListItem } from '@tmo/shared/testing';
import { ReadingListEffects } from './reading-list.effects';
import * as ReadingListActions from './reading-list.actions';

describe('ToReadEffects', () => {
  let actions: ReplaySubject<any>;
  let effects: ReadingListEffects;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [SharedTestingModule],
      providers: [
        ReadingListEffects,
        provideMockActions(() => actions),
        provideMockStore()
      ]
    });

    effects = TestBed.inject(ReadingListEffects);
    httpMock = TestBed.inject(HttpTestingController);
  });

  describe('loadReadingList$', () => {
    it('should work', done => {
      actions = new ReplaySubject();
      actions.next(ReadingListActions.init());

      effects.loadReadingList$.subscribe(action => {
        expect(action).toEqual(
          ReadingListActions.loadReadingListSuccess({ list: [] })
        );
        done();
      });

      httpMock.expectOne('/api/reading-list').flush([]);
    });
  });

  describe('markBookAsRead$', () => {
    it('should return confirmedMarkBookAsFinished action with ReadingListItem, on success', done => {
      const item = createReadingListItem('A')
      actions = new ReplaySubject();
      actions.next(ReadingListActions.markBookAsFinished({item}));

      effects.markBookAsRead$.subscribe(action => {
        expect(action).toEqual(
          ReadingListActions.confirmedMarkBookAsFinished({ item })
        );
        done();
      });

      httpMock.expectOne(`/api/reading-list/${item.bookId}/finished`).flush(item);
    });
 });
});

【问题讨论】:

    标签: angular typescript unit-testing jestjs ngrx-effects


    【解决方案1】:

    模拟 API 调用的错误,而不是刷新。

    it('should return failedMarkBookAsFinishedaction with ReadingListItem, on fail', done => {
          const item = createReadingListItem('A')
          actions = new ReplaySubject();
          actions.next(ReadingListActions.markBookAsFinished({item}));
    
          effects.markBookAsRead$.subscribe(action => {
            expect(action).toEqual(
              ReadingListActions.failedMarkBookAsFinished({ item })
            );
            done();
          });
          // add the second object here to specify a failed request
          httpMock.expectOne(`/api/reading-list/${item.bookId}/finished`).flush(item, { status: 400, statusText: 'Bad Request' });
        });
    

    【讨论】:

    • 谢谢,AliF50,有了这个代码测试用例,运行成功,但我不明白你的评论“在此处添加第二个对象以指定失败的请求”。请您能详细说明一下,以便有帮助吗?
    • stackoverflow.com/questions/46028804/… 是的,看看。您需要使用 status 和 statusText 指定第二个对象,以便 api 调用导致测试失败。
    猜你喜欢
    • 1970-01-01
    • 2022-01-15
    • 2019-06-23
    • 2023-03-13
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多