Angular ngrx效应的单元测试失败

Angular ngrx效应的单元测试失败,angular,unit-testing,jasmine,ngrx,ngrx-effects,Angular,Unit Testing,Jasmine,Ngrx,Ngrx Effects,我正在为effect.ts文件编写单元测试。但由于某些原因,即使我将expect语句更改为dispatch ContactInfoFailed action,它也会通过。我的测试文件中的订阅有问题吗?我不知道这到底是什么原因!或者是否有更好的方法编写此测试? 请在下面找到我的效果和它的测试用例 //特效 import { Actions, Effect, ofType } from '@ngrx/effects'; import { ContactTriageService } from '..

我正在为effect.ts文件编写单元测试。但由于某些原因,即使我将expect语句更改为dispatch ContactInfoFailed action,它也会通过。我的测试文件中的订阅有问题吗?我不知道这到底是什么原因!或者是否有更好的方法编写此测试? 请在下面找到我的效果和它的测试用例

//特效

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
  ) { }
}
//特效

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/core/testing'导入{TestBed};
从'rxjs'导入{of,ReplaySubject,Subject,EMPTY};
从'@ngrx/store'导入{StoreModule};
从“@ngrx/effects/testing”导入{provideMockActions};
从“/effects”导入{ContactInfoEffect};
从“../views/contact-triage/contact-triage.service”导入{ContactTriageService};
从“../reducers/reducers”导入{reducers};
从“../actions/actions”导入{contactInfoSuccessed};
从'src/server/test/mocks'导入{getContactInfoMock};
从'src/server/contact-info/interfaces/contact-info.interface'导入{ContactInfoResponse};
描述('ContactInfoEffect',()=>{
let效应:接触信息效应;
让contactTriageService:contactTriageService;
让行动:主体;
beforeach(异步()=>{
TestBed.configureTestingModule({
导入:[StoreModule.forRoot(还原器)],
供应商:[
联系信息效应,
{
提供:联系咨询服务,
使用价值:{
getContentInfo(){
返回空;
}
}
},
provideMockActions(()=>操作)
]
});
effects=TestBed.get(ContactInfoEffect);
contactTriageService=TestBed.get(contactTriageService);
});
它('如果服务成功返回,()=>{
常量响应:ContactInfoResponse=getContactInfoMock();
const contactTriageService Spy=spyOn(
联系咨询服务,
“getContentInfo”
).及.返回值([
getContactInfoMock()
]));
动作=新的ReplaySubject(1);
下一步(新ContactInfoSuccessed(getContactInfoMock());
effects.fetchContactInfoResponse.subscribe((结果)=>{
期望(结果).toEqual(新联系人信息成功(响应));
});
});
});

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

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

正如您所看到的,这是一个常见的问题,解决方案在任何情况下都不是完美的

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


希望这有帮助

感谢您回复Llorenc,即使我删除了延迟,它也无法正常工作。嗯,有趣的是,如果有,您可以共享“测试”输出吗?它认为问题可能在于“subscribe”上的回调从未被调用,对吗?我认为这一行可能是问题所在:actions=newreplaysubject(1);我的意思是,它似乎应该放在provideMockActions()函数之前,因为如果您在之后创建一个新主题,那么这个新主题没有任何订户。