Angular 如何测试依赖于另一个服务(反过来又依赖于Http服务)的服务/组件?
我对将服务作为依赖项的组件进行单元测试有疑问,而此服务器依赖于Angular 如何测试依赖于另一个服务(反过来又依赖于Http服务)的服务/组件?,angular,unit-testing,http,Angular,Unit Testing,Http,我对将服务作为依赖项的组件进行单元测试有疑问,而此服务器依赖于Http。 我正在读这些文件: 我有与此示例中相同的代码: ngOnInit(): void { this.twainService.getQuote().then(quote => this.quote = quote); } 顺便说一下,这是我的代码: 文档中说,当我测试依赖于其他服务的组件时,我必须: 将此服务设置为模块提供程序 将服务注入组件:twainService=fixture.debugElem
Http
。
我正在读这些文件:
我有与此示例中相同的代码:
ngOnInit(): void {
this.twainService.getQuote().then(quote => this.quote = quote);
}
顺便说一下,这是我的代码:
文档中说,当我测试依赖于其他服务的组件时,我必须:
twainService=fixture.debugElement.injector.get(twainService)代码>
所以问题是:如果我像docs那样做,我会得到错误:
error:没有Http的提供者代码>。显然,出现此错误是因为myGoodsDataService
依赖于Http
服务。我该怎么处理?我这样做了:我创建了简单的javascript对象,并用它模拟了我真正的GoodsDataService
。我还在这个对象中添加了getGoods
方法存根。所有这些都允许我在不注入realGoodsDataService
的情况下测试主要组件。但我对这个解决方案一点也不确定。我认为这是肮脏的,不正确的。单元测试组件/服务的正确方法是什么,它依赖于另一个服务,而另一个服务又依赖于Http
服务?有什么想法吗?只需在测试模块的导入中添加HttpModule
它需要存在,以便可以将Http注入到您的服务中,但Http不会在您的测试中使用,因为您监视您的服务方法。摘要:是的,请结合使用依赖存根和异步服务示例
事实证明,TwainService
实际上根本没有使用Http
或其他依赖项,它只是返回一个承诺:
getQuote(): Promise<string> {
return new Promise(resolve => {
setTimeout( () => resolve(this.nextQuote()), 500 );
});
}
getQuote():承诺{
返回新承诺(解决=>{
setTimeout(()=>resolve(this.nextQuote()),500);
});
}
因此,因为在我们的例子中,被测试的组件依赖于一个服务,而该服务可能有许多自己的依赖项,所以最好通过Angular文档中的WelcomeComponent
/userServiceStub
示例来模拟该服务(请继续阅读以获取警告)。存根对象将有一个用于实际方法名的属性,其值是一个带有语句的未命名函数
现在,很容易在存根中错误地实现同步返回的方法,即使实际方法异步返回。但是您不想这样做,因为被测试的组件可能包含一个.then()
块来处理实际异步方法的响应。因此,请确保存根方法返回封装在承诺中的测试返回值:returnpromise.resolve(mySwappableTestingReturnValue)
最后,因为我们确实在测试一个异步方法(注意事项),it
块也应该使用TwainService
示例中的三个选项之一:angular的async()
/whenStable.then()
、angular的fakeAsync()
/tick()
或jasmine的done
。我还发现promise的常规.then()
块附加到fixture.componentInstance.myAsyncMethod()
上,同样有效(js的异步/也可能等待)
~~~
作为一名间谍新手,我还犯了另一个错误,和.callThrough()
可能会帮助你
例如(幽默地说,它简短而常见):LoginComponent有一个submit btn,其onclick由一个调用this.authService.askAuthServer的logMeIn方法处理。askAuthServer使用Http
测试按钮点击是否正确调用logMeIn的规范是同步的,我们不关心logMeIn返回的值,我们只关心它是否被调用(UI事件在主线程上同步处理,如果这对您有帮助的话)。测试logMeIn中决策逻辑的规范确实需要返回值,因此需要异步测试,因此我们使用whenStable().then()
因此,您很高兴在每个
之前的中创建一个spyOn logMeIn,但是click规范成功,而异步逻辑规范失败。在click spec中,您会注意到askAuthServer没有执行,尽管我们的spy成功地.tohaveBeenCall()
。发生了什么事?那是因为间谍阻止了对洛格明的处决,甚至在我们选择不等待洛格明回来之前。因此,在逻辑规范中,尽管它可能不使用logMeInSpy,但间谍仍然在阻止logMeIn(以及askAuthServer)的执行,即使我们已经正确地设置了异步部分
要理解这一点,在每个
之前的中创建spy时,可以使用和.callThrough()
,以允许在两个规范中执行logMeIn,或者将spy移动到click规范中,这样做不会影响逻辑规范。我认为这确实是个好主意。我也在想同样的事情。但为什么医生不说呢?这是显而易见的吗?我不会说这是令人生畏的,因为了解每件事的运作方式需要一些时间。但我要说的是,一旦你了解了它是如何工作的,听起来就合乎逻辑了。我同意,考虑到他们将twain服务作为使用HTTP的服务引入,他们应该解释如何在测试中提供假的HTTP服务,或者如何导入HttpModule。你应该提出一个问题。