【问题标题】:Angular2 / RxJS / Jasmine : How to test Observable chain/sequence (operators)Angular2 / RxJS / Jasmine:如何测试 Observable 链/序列(操作员)
【发布时间】:2017-07-17 08:05:34
【问题描述】:

作为 Angular 4 项目的一部分,我正在拼命地尝试用 Jasmine 测试一个函数,该函数使用运算符实现 RxJs 链/序列(在我的例子中为map)。

class RendezVousResolver {

  searchRendezVous(code: string): Observable<any> {
    return Observable.create(observer => {
      this.userCardService.readCard(code).map(userData => {
        this.rendezVousService.search(userData).subscribe(
          result => {
            observer.next(result);
          },
          error => {
            observer.error(error);
          }
        );
      });
    });
  }

}

我的单元测试使用 2 个模拟来“模拟”两个服务层:userCardServicerendezVousService

class MockUserCardService {

  readCard(code: string): Observable<any> {
    return Observable.of('<data></data>');
  }

}

class MockRendezVousService {

  search(userData : string): Observable<any> {
    return Observable.of({
      rdvs: []
    });
  }

}

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [
      RendezVousResolver,
      { provide: RendezVousService, useClass: MockRendezVousService },
      { provide: SwcVitaleReadingService, useClass: MockSwcVitaleReadingService }
    ]
  });
  fixture = TestBed.get(RendezVousResolver);
});

这里是我的单元测试。

it('should return the expected response', async(() => {
  fixture.resolve(undefined, undefined).subscribe(
    rdvs => {
      console.log("expect");
      expect(rdvs).toEqual({
        rdvs: []
      });
    },
    error => {
      console.log("fail");
      fail('No error was expected');
    }
  );
}));

当我执行它时,测试似乎没有等待被模拟的 Observable 发出的事件。 expectedfail 均未执行。我很确定,因为控制台中没有记录任何内容。

我发现使此测试通过的唯一方法是不使用运算符 map 并将我的代码替换为嵌套订阅。

searchRendezVous(code: string): Observable<any> {
  return Observable.create(observer => {
    this.userCardService.readCard(code).subscribe(
      userData => {
        this.rendezVousService.search(userData).subscribe(
          rdvs => {
            observer.next(rdvs);
          },
          error => {
            observer.error(error);
          }
        )
      },
      error => {
        observer.error(error);
      }
    );
  });
}

除了map(例如zip)以外的其他运营商,我也遇到了同样的问题。

感谢您的帮助。

【问题讨论】:

标签: angular unit-testing jasmine rxjs observable


【解决方案1】:

您可以通过将 Observable.create 替换为 RxJs 中的现有行为/功能来简化您的 RendezVousResolver

class RendezVousResolver {
  searchRendezVous(code: string): Observable<any> {
    return this.userCardService.readCard(code)
      .mergeMap(userData => this.rendezVousService.search(userData));
  }
}

这样你就可以减少自己遇到的边缘情况。

通过将readCardsearch 与返回Rx.Observable.from([]) 的模拟交换与预期的模拟数据交换,可以立即完成测试。只需在您的 searchRendezVous() 上调用 .toPromise() 即可完成这项工作,而无需任何调度程序魔法。

it('returns data', () => {
  return searchRendezVous('foo')
    .toPromise()
    .then(searchResults => {
      expect(searchResults).to.not.be.empty();//assert what you need
    })
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 2017-08-17
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多