【问题标题】:Unit testing a function with return value within subscribe在订阅中对具有返回值的函数进行单元测试
【发布时间】:2020-05-07 07:16:12
【问题描述】:

我有一个功能需要进行单元测试,但我不知道如何处理。 简化:

someFunction(): boolean {
 this.service.login().subscribe(response => {
  if (response) {
    return someOtherFunction();
  }
 });
}

someOtherFunction(): boolean {
 this.service.otherTask().subscribe(response => {
  if (response) {
    return true;
  }
 });
}

在这种情况下,我想测试someFunction 的结果。但是,这不起作用:

describe('someFunction', () => {
  it('returns true', () => {
   serviceSpy.login.and.returnValue(of({response: response}));
   serviceSpy.otherTask.and.returnValue(of({response: otherResponse}));
   result = component.someFunction();
   expect(result).toEqual(true);
 });
});

ServiceSpy 已在此块之前配置。 我可以看到函数已执行并返回 true。但是,目前我要求result,它仍然未定义。测试框架不会等待一切都完成。我曾尝试使用 async、fakeAsync、done(),但这些都不起作用。 有没有办法测试someFunction的返回值?

【问题讨论】:

  • someFunction 没有返回值。 someOtherFunction 也没有。我很惊讶 TypeScript 编译器没有对你大喊大叫。
  • 我很惊讶它完全有效。它似乎确实做了它需要做的事情...... someFunction 是身份验证保护的 canActivate 是否重要?
  • @Century :这是一个糟糕的代码。请重构它
  • 我无法想象它会像 canActivate 那样做它需要做的事情。它返回 undefined,即 false-y,因此路由将永远被激活。
  • 幸运的是,大部分流量在没有订阅的情况下遵循不同的路径。尽管如此,这部分似乎以某种方式工作......我的编译器也没有警告我。无论如何,我让 someFunction 返回一个 Observable (幸运的是,这对 canActivate 来说很好)并返回登录名,但使用管道和映射在那里。我应该将其发布为答案吗?

标签: angular observable karma-jasmine testbed


【解决方案1】:

问题出在函数内部,它们在subscribe 内部返回结果,这不起作用,您需要返回可观察对象或使用局部变量。

someFunction(): Observable<boolean> {
 return this.service.login().pipe(
   first(),
   switchMap(res => res ? this.someOtherFunction() : of(undefined)),
 );
}

someOtherFunction(): Observable<boolean> {
 return this.service.otherTask().pipe(
   first(),
   map(response => !!response),
 );
}

然后在你的测试中你可以做

describe('someFunction', (done) => {
  it('returns true', () => {
   serviceSpy.login.and.returnValue(of({response: response}));
   serviceSpy.otherTask.and.returnValue(of({response: otherResponse}));
   component.someFunction().subscribe(result => {
     expect(result).toEqual(true);
     done();
   });
 });
});

【讨论】:

    【解决方案2】:

    从@satanTime 和 cmets 的答案以及更多的互联网搜索中获得灵感,我编辑了我的代码并进行了如下测试。 someOtherFunction 似乎没有任何问题的订阅,所以我在简化时省略了它。

    someFunction(): Observable<boolean> {
     return this.service.login().pipe(map(response => {
      if (response) {
        return someOtherFunction();
      }
     }));
    }
    
    someOtherFunction(): boolean {
        return true;
    }
    

    测试:

    describe('someFunction', () => {
      it('returns true', (done) => {
       serviceSpy.login.and.returnValue(of({response: response}));
       serviceSpy.otherTask.and.returnValue(of({response: otherResponse}));
       component.someFunction().subscribe(result => {
       expect(result).toEqual(true);
       done();
       });
     });
    });
    

    【讨论】:

      猜你喜欢
      • 2019-04-15
      • 1970-01-01
      • 2017-11-23
      • 2018-11-02
      • 1970-01-01
      • 2013-04-03
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多