【问题标题】:Angular Unit test - how to mock a provider in component which was being called by ngrx/effect during store dispatchAngular Unit test - 如何在商店调度期间模拟由ngrx / effect调用的组件中的提供者
【发布时间】:2018-11-23 21:00:03
【问题描述】:

我有一个组件,在 ngOninit 内部,我正在调度一个由 ngrx/effect 处理的操作,以从服务 API 获取一些数据。我正在编写单元测试并想在 ngOninit 中模拟服务调用,以便不调用原始 API。但是仍然调用了原始 API,可能是因为它是从效果处理的。我应该如何处理这个问题,以便停止实际的 API 调用并改为调用模拟服务 API?

组件代码:

ngOnInit() {
   this.sectionId$ = this.store.select(reducers.getSectionIDFromAppState).subscribe((sectionID) => {
   if (sectionID) {
     this.store.dispatch(new layoutActions.GetLogFormatListAction(sectionID));
  }
}

操作代码:

export class GetLogFormatListAction implements Action {
type = ActionTypes.GET_LOG_FORMAT_LIST;
constructor(public payload?: any) {
    this.payload = payload;
}

}

效果代码:

@Effect()
getLogFormatList$: Observable<Action> = this.actions$
    .ofType(layoutActions.ActionTypes.GET_LOG_FORMAT_LIST)
    .mergeMap((action: any) => {
        return this.layoutService.getLogFormatList(action.payload)
            .map(logFormatList => new layoutActions.GetLogFormatListSuccessAction(logFormatList))
            .catch(error => Observable.of(new layoutActions.GetLogFormatListFailureAction(error)));
    });

布局.service.ts

getLogFormatList(sectionId): Observable<any> {
const requestData = {
  endpoint: environment.endpoints.GET_LOG_FORMAT_LIST.endpoint + sectionId,
  params: {
  }
};
return this.httpRequestWrapperService.fetchData(requestData);  }

我的规范代码:

beforeEach(async(() => {
TestBed.configureTestingModule({
  declarations: [
    LogviewerWidgetConfigComponent,
    MockComponent({ selector: 'app-logviewer-config-template', inputs: ['logformatList', 'widgetConfig' , 'index'] }),
    MockComponent({ selector: 'app-widget-config-header', inputs: ['model'], outputs: ['closeWidgetConfig'] }),
  ],
  imports: [FormsModule, StoreModule.forRoot(reducers)],
  providers: [{ provide: LayoutService, useClass: MockLayoutService }]
}).compileComponents();  }));

beforeEach(() => {
store = TestBed.get(Store);
spyOn(store, 'dispatch').and.callThrough();
fixture = TestBed.createComponent(LogviewerWidgetConfigComponent);
component = fixture.componentInstance;
fixture.detectChanges();  });

模拟服务:

class MockLayoutService {
  getLogFormatList(param: any): Observable<any> {
   return Observable.of(null);
  }
}

【问题讨论】:

  • 您可以尝试在overrideComponent 中提供MockLayoutService 吗?
  • 即使我也有同样的问题。你得到答案了吗?

标签: angular ngrx ngrx-effects angular-unit-test


【解决方案1】:

你没有模拟你的 API 调用,你模拟了另一个服务。

如果您想模拟您的 API 调用,请进行此模拟:

const storeMock = {
  select: () => Observable.of(null),
  dispatch: () => null
};

并在您的测试平台中提供它:

providers: [
  { provide: LayoutService, useClass: MockLayoutService },
  { provide: Store, useValue: storeMock }
]

(我不知道您使用的依赖项,但我认为如果您模拟它的服务,您可能必须从 imports 中删除 StoreModule)。

完成后,您的调用将不再调用 API,而是调用 mock。

【讨论】:

  • 感谢您的回答。这里的主要问题不是商店,而是考虑原始服务而不是模拟服务的效果
  • 你的效果是从哪里调用的?
猜你喜欢
  • 2018-03-23
  • 2020-07-14
  • 1970-01-01
  • 2018-04-19
  • 2017-10-31
  • 2019-01-24
  • 2022-10-21
  • 2020-11-18
  • 2019-11-01
相关资源
最近更新 更多