【问题标题】:Unit tests for ngrx-effect failsngrx-effect 的单元测试失败
【发布时间】:2019-09-21 13:36:50
【问题描述】:

我正在为我的 effect.ts 文件编写单元测试。但由于某种原因,即使我将期望语句更改为调度 ContactInfoFailed 操作,它也会通过。我的测试文件中的订阅有问题吗?我无法弄清楚这到底是什么原因!或者如果有更好的方法来编写这个测试? 请在下面找到我的效果和它的测试用例。

// effects.ts

import { Actions, Effect, ofType } from '@ngrx/effects';
import { ContactTriageService } from '../views/contact-triage/contact-triage.service';
import {
  CONTACT_INFO_RESPONSE_REQUESTED, ContactInfoSucceeded, ContactInfoFailed , 
  CONTACT_INFO_SELECTION_RESPONSE_REQUESTED, ContactInfoSelectionSucceeded, 
  ContactInfoSelectionFailed,
  ContactInfoServiceResponse
} from '../actions/actions';
import { mergeMap, map, catchError, delay } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';

@Injectable()
export class ContactInfoEffect {
  @Effect()
  fetchContactInfoResponse = this.actions.pipe(
    ofType(CONTACT_INFO_RESPONSE_REQUESTED),
    delay(250),
        mergeMap((action) =>
            this.contactTriageService.getContentInfo().
            pipe(map((contacts) => new ContactInfoSucceeded(contacts)),           
            catchError(() => of(new ContactInfoFailed()))
             ),
        )
  )

  constructor(
    private actions: Actions,
    private contactTriageService: ContactTriageService
  ) { }
}

// effects.spec.ts

import { TestBed } from '@angular/core/testing';
import { of, ReplaySubject, Subject, EMPTY } from 'rxjs';
import { StoreModule } from '@ngrx/store';
import { provideMockActions } from '@ngrx/effects/testing';
import { ContactInfoEffect } from './effects';
import { ContactTriageService } from '../views/contact-triage/contact-triage.service';
import { reducers } from '../reducers/reducers';
import { ContactInfoSucceeded } from '../actions/actions';
import { getContactInfoMock } from 'src/server/test/mocks';
import { ContactInfoResponse } from 'src/server/contact-info/interfaces/contact-info.interface';

describe('ContactInfoEffect', () => {
  let effects: ContactInfoEffect;
  let contactTriageService: ContactTriageService;
  let actions: Subject<any>;

  beforeEach(async () => {
    TestBed.configureTestingModule({
      imports: [StoreModule.forRoot(reducers)],
      providers: [
        ContactInfoEffect,
        {
          provide: ContactTriageService,
          useValue: {
            getContentInfo() {
              return EMPTY;
            }
          }
        },
        provideMockActions(() => actions)
      ]
    });
    effects = TestBed.get(ContactInfoEffect);
    contactTriageService = TestBed.get(ContactTriageService);
  });

  it('should dispatch `ContactInfoSucceeded` if the service returns successfully', () => {
    const response:ContactInfoResponse =  getContactInfoMock();
    const contactTriageServiceSpy = spyOn(
        contactTriageService,
      'getContentInfo'
    ).and.returnValue(of( [
        getContactInfoMock()
      ]));
    actions = new ReplaySubject(1);
    actions.next(new ContactInfoSucceeded(getContactInfoMock()));
    effects.fetchContactInfoResponse.subscribe((result) => {   
      expect(result).toEqual(new ContactInfoSucceeded(response));
    });
  });
});

【问题讨论】:

    标签: angular unit-testing jasmine ngrx ngrx-effects


    【解决方案1】:

    delay() 运算符可能导致您的测试无法按预期工作的一个原因。 delay() 运算符使您的流/效果完全异步

    为了像这样正确测试异步流,您应该使您的测试断言异步,或者更推荐,您可以通过模拟调度程序来同步您的流。以下是一些讨论和解释的有用链接:

    Testing and mocking lettable operators in RxJS 5.5

    https://github.com/redux-observable/redux-observable/issues/180

    https://github.com/angular/angular/issues/25457

    如您所见,是一个常见的问题,而且解决方案无论如何都不是完美的。

    提示:您可以尝试暂时删除 delay() 运算符,看看它是否有效。

    希望这会有所帮助!

    【讨论】:

    • 感谢 Llorenc 的回复,即使我消除了延迟,它也无法正常工作
    • 嗯,有趣,如果有的话,你能分享一下“测试”输出吗?它认为问题可能是“订阅”上的回调从未被调用过,对吗?我认为这行可能是问题所在:actions = new ReplaySubject(1);我的意思是,它似乎应该放在 provideMockActions() 函数之前,因为如果你在之后创建一个新的主题,这个新主题没有任何订阅者。
    猜你喜欢
    • 2019-02-22
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    相关资源
    最近更新 更多