首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何测试依赖于另一个依赖于Http服务的服务/组件?

如何测试依赖于另一个依赖于Http服务的服务/组件?
EN

Stack Overflow用户
提问于 2017-05-30 22:05:39
回答 2查看 1.2K关注 0票数 3

我对以服务作为依赖项的组件进行单元测试有疑问,这个服务器依赖于Http。我正在读这个文档:使用异步服务测试组件

我的代码与本例中的代码完全相同:

代码语言:javascript
代码运行次数:0
运行
复制
  ngOnInit(): void {
    this.twainService.getQuote().then(quote => this.quote = quote);
  }

顺便提一下,这里是我的代码:代码

docs说,当我测试依赖于另一个服务的组件时,我必须:

  1. 将此服务设置为模块提供程序
  2. 将服务注入组件:twainService = fixture.debugElement.injector.get(TwainService);
  3. 设置间谍:spy = spyOn(twainService, 'getQuote').and.returnValue(Promise.resolve(testQuote));

我也这样做:这是我的规范文件:规格文件。我在第21行提供服务,29次注射服务,32次设置间谍。

所以问题是:如果我做任何事情都像docs说的那样,我就会出错:Error: No provider for Http!。显然,出现此错误是因为我的GoodsDataService依赖于Http服务。我该怎么处理呢?我这样做了:我创建了一个简单的javascript对象,并用它来模拟我真正的GoodsDataService。我还在这个对象中添加了getGoods方法存根。所有这些都允许我测试主组件,而不需要注入真正的GoodsDataService。但我对这个解决办法一点也不确定。我认为这是肮脏和不正确的。单元测试组件/服务依赖于另一个依赖于Http服务的服务的正确方式是什么?有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-30 22:09:00

只需在测试模块的导入中添加HttpModule即可。

它需要在那里,这样才能在您的servie中注入Http,但是由于您监视您的服务方法,所以不会在您的测试中使用Http。

票数 1
EN

Stack Overflow用户

发布于 2017-10-31 18:27:01

摘要:是的,使用依赖存根和异步服务角度文档示例的组合。

事实证明,TwainService实际上根本不使用Http或其他依赖项,它只是返回了一个承诺:

代码语言:javascript
代码运行次数:0
运行
复制
getQuote(): Promise<string> {
    return new Promise(resolve => {
      setTimeout( () => resolve(this.nextQuote()), 500 );
    });
}

因此,由于在我们的示例中,所测试的组件依赖于一个可能具有多种依赖项的服务,所以最好通过角度文档中的WelcomeComponent/userServiceStub示例来模拟该服务(请继续阅读警告)。存根对象将有一个实方法名的属性,它的值是一个未命名的函数及其语句。

现在,即使真正的方法异步返回,也很容易在存根中错误地实现一个同步返回的方法。但是,您不想这样做,因为测试中的组件可能包含一个.then()块来处理真正的异步方法的响应。因此,确保存根方法返回封装在承诺:return Promise.resolve(mySwappableTestingReturnValue)中的测试-返回值。

最后,由于我们确实在测试异步方法(警告),it块还应该使用TwainService示例中的三个选项之一:角的async()/whenStable.then()、角的fakeAsync()/tick()或茉莉的done。我还发现,在.then()中附加到fixture.componentInstance.myAsyncMethod()中的诺言的常规async块同样工作得很好(很可能也是js的async/await )。

代码语言:javascript
代码运行次数:0
运行
复制

作为一个间谍新手,我也犯了另一个错误,.and.callThrough()可能会帮助你。

例如(很简单,很常见):LoginComponent有一个submit-btn,其onclick由调用this.authService.askAuthServer的logMeIn方法处理。askAuthServer使用Http。

测试按钮单击是否正确调用logMeIn的规范是同步的,我们不关心logMeIn返回的值,我们只关心调用它(并且UI事件在主线程上被同步处理,如果这对您有帮助的话)。在logMeIn中测试决策逻辑的规范确实需要返回的值,因此需要异步测试,因此我们使用whenStable().then()

因此,您可以愉快地在spyOn logMeIn中创建beforeEach,但是单击规范成功,异步逻辑规范失败。在单击规范中,您会注意到askAuthServer没有执行,尽管我们的间谍成功地执行了.toHaveBeenCalled()。怎么一回事?这是因为间谍阻止了logMeIn的执行,甚至在我们选择不等待logMeIn回来之前。因此,在逻辑规范中,尽管间谍可能不使用logMeInSpy,但是即使我们正确地设置了异步部件,间谍仍然阻止logMeIn (和askAuthServer的执行)的执行。

要理解这一点,或者在beforeEach中创建间谍时使用beforeEach,或者在两个规范中允许执行logMeIn的,或者将间谍移动到点击规范中,这样不会影响逻辑规范。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44272683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档