简体   繁体   中英

How to test angular 5 component with rxjs 5 forkJoin

I have a ResultsComponent in my application, where I am making two service calls at the same time joining both observable by using a rxjs forkJoin operator. I want to mock the data for the rxjs operator. I have google lot time and tried different ways, but didn't find a way to do it. can anyone please help me.

angular version: 5.2.9 rxjs version: 5.5.7 angular-cli: 1.6.6

getting this error at forkJoin statement in results.component.ts

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

results.component.ts

@Component({
  selector: "app-results",
  templateUrl: "./results.component.html",
  styleUrls: ["./results.component.scss"]
})
export class ResultsComponent 
  implements OnInit, OnDestroy {
  searchForm: FormGroup;


  constructor(
    private rxnsSearchService: RxnsSearchService,
    private rxnsSearchHitCountService: RxnsSearchHitCountService,
    public store: Store<fromAppReducer.AppState>,
    private route: ActivatedRoute,
    public formBuilder: FormBuilder,
    public router: Router
  ) {

  }

  ngOnInit() {

    this.route.queryParams.subscribe(params => {
      this.searchForm = this.formBuilder.group({
        searchInput: new FormControl(params.q, Validators.required),
        searchType: new FormControl(params.searchType),
        searchBy: new FormControl(params.searchBy)
      });
      this.store.dispatch(new AppActions.ChemQueryString(params.q));
      const rxnsObservable: Observable<Array<any>> = this.rxnsSearchService.getReactions(params, 0);
      const headCountObservable: Observable<number> = this.rxnsSearchHitCountService.getHitCount(params);
      forkJoin([rxnsObservable, headCountObservable]).subscribe(results => {
        this.reactions = results["0"];
        this.total = results["1"];
      }, (error) => {
        console.log(error);
      });
    });
    this.store.select("rxnState").subscribe(data => {
      console.log(data);
      this.searchString = data.slice(-1)[0].searchString;
    });
  }
  ngOnDestroy() {}
}

results.component.spec.ts

const dummydata = [
  {
    ruid: "02b01f46288b4f71950d03856bc8f173",
    rxnString: "Cl.NCCC1(C(F)(F)F)CC1.NCC1=CC=CC(NC"
  },
  {
    ruid: "02b01f46288b4f71950d03856bc8f173",
    rxnString: "Cl.NCCC1(C(F)(F)F)CC1.NCC1=CC=CC(NC"
  }
];
const dummyParams = {q: "[H]N(C(=O)C([H])([H])C)C1([H])CCCC22", searchType: "SUBSTRUCTURE", searchBy: "PRODUCT"};

class RouterStub {
  navigate(commands: any[], extras?: NavigationExtras) { }
}
class ActivatedRouteStub {
  private _testParams: {};
  private subject = new BehaviorSubject(this._testParams);
   queryParams = this.subject.asObservable();
  setQueryParams(params: Params) {
    this._testParams = params;
    this.subject.next(params);
  }
}

describe("ResultsComponent", () => {
  beforeEach(() => {
    activatedRoute = new ActivatedRouteStub();
  });
  let component: ResultsComponent;
  let injector;
  let store: Store<any>;
  let fixture: ComponentFixture<ResultsComponent>;
  let rxnsSearchService: RxnsSearchService;
  let rxnsSearchHitCountService: RxnsSearchHitCountService;
  let activatedRoute: ActivatedRouteStub;

  beforeEach(async(() => {

    TestBed.configureTestingModule({
      imports: [
        ResultsModule,
        NgxPaginationModule,
        HttpClientTestingModule,
        RouterTestingModule,
        StoreModule.forRoot(fromAppReducer.reducers)
      ],
      declarations: [ ],
      providers: [
          RxnsSearchService,
          RxnsSearchHitCountService,
        { provide: ActivatedRoute, useValue: activatedRoute },
        { provide: Router, useClass: RouterStub},
        FormBuilder
      ]
    }).compileComponents();
    injector = getTestBed();
    rxnsSearchService = injector.get(RxnsSearchService);
    rxnsSearchHitCountService = injector.get(RxnsSearchHitCountService);
    spyOn(rxnsSearchService, 'getReactions').and.returnValue(Observable.of(dummydata));
    spyOn(rxnsSearchHitCountService, 'getHitCount').and.returnValue(Observable.of(300));
    store = injector.get(Store);
  }));

  beforeEach(async(() => {
    activatedRoute.setQueryParams(dummyParams);
    fixture = TestBed.createComponent(ResultsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }));

  it("should create results component", () => {
    expect(component).toBeTruthy();
  });
});

I faced the same question recently and solved it by pulling the forkjoin out into its own method, then creating a spy to return my desired values.

ngOnInit() {

  this.route.queryParams.subscribe(params => {
    this.searchForm = this.formBuilder.group({
      searchInput: new FormControl(params.q, Validators.required),
      searchType: new FormControl(params.searchType),
      searchBy: new FormControl(params.searchBy)
    });
    this.store.dispatch(new AppActions.ChemQueryString(params.q));
    const rxnsObservable: Observable<Array<any>> = this.rxnsSearchService.getReactions(params, 0);
    const headCountObservable: Observable<number> = this.rxnsSearchHitCountService.getHitCount(params);

    const data = this.getData(rxnsObservable, headCountObservable); 
    this.reactions = data["0"];
    this.total = data["1"];
  });
  this.store.select("rxnState").subscribe(data => {
    console.log(data);
    this.searchString = data.slice(-1)[0].searchString;
  });
}

getData(req1, req2) {
  forkJoin([req1, req2]).subscribe(results => {
    return results;
  }, (error) => {
    console.log(error);
  });
}

Then your test can be something like this:

spyOn(component, 'getData').and.returnValue([foo, bar]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM