Модульные тесты для ngrx-эффекта не пройдены - PullRequest
2 голосов
/ 03 мая 2019

Я пишу юнит-тесты для моего файла effect.ts. Но по какой-то причине он проходит, даже если я изменяю оператор ожидания для отправки действия ContactInfoFailed Есть ли проблема с подпиской в ​​моем тестовом файле? Я не могу понять, что именно является причиной этого! Или, если есть лучший способ написать этот тест? Пожалуйста, найдите ниже мой эффект, и это контрольный пример.

// effect.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
  ) { }
}

// effect.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 голосов
/ 03 мая 2019

Одной из причин, по которой ваш тест может не работать должным образом, является оператор delay () . Оператор delay () делает ваш поток / эффект полностью асинхронным .

Для правильного тестирования асинхронного потока, подобного этому, необходимо сделать асинхронное тестовое утверждение или более рекомендуемым, вы можете синхронно запланировать свой поток , издеваясь над планировщиком . Вот несколько полезных ссылок, где обсуждается и объясняется:

Тестирование и имитация операторов допустимых значений в RxJS 5.5

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

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

Как видите, это общая проблема, и решение в любом случае не идеальное.

Совет: вы можете попытаться временно удалить оператор delay () и посмотреть, работает ли он.

Надеюсь, это поможет!

...