How to test Subject with jasmine marbles

牧云@^-^@ 提交于 2019-12-07 05:26:59

问题


Angular 6, Rxjs, Jest, Jasmine-marbles.

very common scenario: a component that searches for server-side items. In the component, there are some controls that can change search critera, and I'd like to code in "reactive-style". So in the component code I have something like this:

class SearchComponent  implements OnInit {
  public searchData: SearchData = {};
  public searchConditions$ = new Subject<SearchData>();

  constructor(private searchService: SearchService) { }

  public results$: Observable<ResultData> = this.searchConditions$.pipe(
    distinctUntilChanged(this.compareProperties), // omissis but it works
    flatMap(searchData => this.searchService.search(searchData)),
    shareReplay(1)
  );

  // search actions
  ngOnInit() {
    this.searchConditions$.next(this.searchData);
  }
  public onChangeProp1(prop1: string) {
    this.searchData = { ...this.searchData, prop1 };
    this.searchConditions$.next(this.searchData);
  }
  public onChangeProp2(prop2: string) {
    this.searchData = { ...this.searchData, prop2 };
    this.searchConditions$.next(this.searchData);
  }
}

That's, a Subject that fires search conditions each time something in the UI has changed.

Now I'd like to test that search service will be called only for distinct input. I can do it "without marbles" in this way:

test('when searchConditions$ come with equal events search service will not be called more than once', (done: any) => {
    service.search = jest.fn(() => of(TestData.results));
    component.results$.subscribe({
        complete: () => {
            expect(service.Search).toHaveBeenCalledTimes(1);
            done();
        }
    });

    component.searchConditions$.next(TestData.searchCriteria);
    component.searchConditions$.next(TestData.searchCriteria);
    component.searchConditions$.next(TestData.searchCriteria);
    component.searchConditions$.complete();
});

Now I'd like to convert this test using jasmine marbles, but I don't know how...

I'd like something like this:

test('when searchConditions$ come with equal events search service will not be called more than once', (done: any) => {
    service.search = jest.fn(() => of(TestData.results));
    component.searchConditions$ = cold('--a--a|', { a : TestData.searchCriteria});
    const expected = cold('--b---|', { b : TestData.results});
    expect(component.results$).toBeObservable(expected);
});

Obviously, it doesn't work...

Update

somehow close...using a "test helper"

test('when searchConditions$ comes with equal events search service will not be called more than once - marble version', () => {
    service.search = jest.fn(() => of(TestData.results));
    const stream   = cold('--a--a|', { a : TestData.searchCriteria});
    const expected = cold('--b---|', { b : TestData.results});
    stubSubject(component.searchConditions$, stream);
    expect(component.results$).toBeObservable(expected);
});


// test helpers
const stubSubject = (subject: Subject<any> , marbles: TestObservable) => {
    marbles.subscribe({
        next: (value: any) => subject.next(value),
        complete: () => subject.complete(),
        error: (e) => subject.error(e)
    });
};

来源:https://stackoverflow.com/questions/52081332/how-to-test-subject-with-jasmine-marbles

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!