ngrx效果的单元测试失败

时间:2019-05-03 02:13:45

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

我正在为我的effect.ts文件编写单元测试。但是由于某种原因,即使我更改了Expect语句以调度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));
    });
  });
});

1 个答案:

答案 0 :(得分:0)

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()运算符,并查看其是否有效。

希望这会有所帮助!