如何在Angular中对带有订阅的嵌套服务方法进行单元测试

时间:2020-10-20 23:29:49

标签: angular typescript

我有一个这样的服务类,并尝试添加我无法弄清楚的单元测试用例,以及如何使用订阅测试嵌套方法。

TestService {
  constructor(@Inject(ENV) private env,
              private userService: UserService,
              private addressService: AddressService) {}

  public getDetails(): void {
    this.getUser().subscribe((user) => {
      if (user && user !== null) {
        this.addressService.getAddress(user).subscribe((address) => {
          this.addressService.updateAddress(user).subscribe(() => {
          
          });
        });
      }
    });
  }

  private getUser(): Observable<string> {
    return userService.findUser().pipe(map((response: any) => response.output.user), take(1));
  }
}

通过监视方法并返回一些模拟数据尝试了几种情况,但没有用。

这是我尝试过的,期望是如果用户为null,则不应从addressService调用getAddress(),这会给我错误,

it('get user should not call if user is null', async(() => {
  service.getDetails();
  spyOn(userService, 'getUser').and.returnValue(of('TEST'));
  const addressServiceSpy = spyOn(addressService, 'getAddress');
  expect(addressServiceSpy).toHaveBeenCalledWith('TEST');
}));

错误:

预期:“ TEST” 通话次数:0

1 个答案:

答案 0 :(得分:0)

我相信您会发现由于过于复杂而难以测试代码。这是一个好习惯,从不进行订阅

让我们尝试将代码分成小块以便于测试

  private getUser(): Observable<string> {
    return userService.findUser().pipe(
     map(({output}) => output.user), 
     take(1));
  }
  public getDetails(): Observable<any> {
    return this.getUser().pipe(
      mergeMap(user => user ? forkJoin([
        this.addressService.getAddress(user), 
        this.addressService.updateAddress(user)]) : of(null)),
      map(([address]) => address)
    )
  }

现在我们可以简单地在测试中订阅可观察的

it('get user should not call if user is null', async(() => {
  spyOn(userService, 'getUser').and.returnValue(of(null));
  service.getDetails().subscribe({
    next: res => {
      expect(res).toBeNull();
    }
  });
  
}));