2017-05-30 93 views
1

我有问题关于单元测试服务作为依赖的组件和此服务器取决于Http。 我读这个文档:Test a component with an async service如何测试一个服务/组件依赖于另一个服务,而这又取决于Http服务?

我真的有相同的代码,就像这个例子:

ngOnInit(): void { 
    this.twainService.getQuote().then(quote => this.quote = quote); 
    } 

这里的方式是我的代码:code

的文档说,当我测试组件这取决于另一项服务,我必须:

  1. 将此服务设置为模块提供商
  2. 注入组件
  3. 获得服务:它twainService = fixture.debugElement.injector.get(TwainService);

  4. 安装间谍:spy = spyOn(twainService, 'getQuote').and.returnValue(Promise.resolve(testQuote));

我做的一样: 这里是我的规格文件:spec file。 我在第21行提供服务,我在29注入服务,我设置间谍在32.

所以的问题:如果我做的一切像​​文档说我得到的错误:Error: No provider for Http!。很明显,这个错误是因为我的GoodsDataService取决于Http服务。我应该如何处理它?我做到了这一点:我创建了简单的JavaScript对象,并用它嘲笑了我的真实GoodsDataService。我还在此对象中添加了getGoods方法存根。所有这些东西都允许我在不注入真实GoodsDataService的情况下测试主要组件。但我不确定这个解决方案。我认为它很脏并且不正确。什么是单元测试组件/服务的正确方式取决于另一个服务,而这又取决于Http服务?有什么想法吗?

回答

1

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

它需要在那里,以便Http可以注入您的服务,但Http不会用于您的测试,因为你监视你的服务方法。

+0

我觉得这是个好主意。我在想同样的事情。但为什么docs不说呢?这是明显的吗? –

+0

我不会说这是有意义的,因为理解如何一切工作都需要一些时间。但我会说,一旦你明白它如何炒作,这听起来合乎逻辑。我同意,鉴于他们将使用HTTP的服务作为服务引入,他们应该解释如何在测试中提供假的Http服务,或者如何导入HttpModule。你应该打开一个问题。 –

0

摘要:是的,使用依赖存根和异步服务Angular doc示例的组合。

原来,TwainService实际上并未使用Http或所有其他依赖,它只是返回一个承诺:

getQuote(): Promise<string> { 
    return new Promise(resolve => { 
     setTimeout(() => resolve(this.nextQuote()), 500); 
    }); 
} 

,是因为在我们的情况下,试验下的部件取决于有一个潜在的服务大量的依赖关系,最好通过Angular文档中的示例来嘲笑该服务(请继续阅读以了解警告)。存根对象将具有真实方法名称的属性,其值是具有其语句的未命名函数。

现在,很容易错误地在存根中同步返回一个方法,尽管真正的方法是异步返回的。你不想这样做,因为被测组件可能包含一个.then()块来处理真正的异步方法的响应。因此,请确保您的存根方法返回包含在承诺中的testing-return-value:return Promise.resolve(mySwappableTestingReturnValue)

最后,因为我们的确测试一个异步方法(警告),则it块应该也使用在TwainService示例的三个选项之一:角的async()/whenStable.then(),角的fakeAsync()/tick(),或茉莉花的done。我还发现承诺的.then()块附加到fixture.componentInstance.myAsyncMethod()的作品同样好(也可能是js的async/await)。

~~~

作为间谍新人,我还做了另外一个错误,其中.and.callThrough()可以帮助你。例如(幽默我,它很短并且很常见):LoginComponent有一个submit-btn,它的onclick由一个logMeIn方法处理,他调用this.authService.askAuthServer。 askAuthServer使用Http。

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

因此,您很高兴在beforeEach中创建spyOn logMeIn,但click spec成功,异步逻辑规范失败。在点击规范中,您会注意到askAuthServer不会执行,尽管我们的间谍成功地登录了.toHaveBeenCalled()。到底是怎么回事?这是因为在我们选择不等待logMeIn返回之前,间谍阻止了logMeIn的执行。因此,在逻辑规范中,即使我们已经正确设置了异步部分,虽然它可能不使用logMeInSpy,但间谍仍然阻止logMeIn(和askAuthServer)的执行。

理解的是,无论是在beforeEach创建间谍的时候,要使用.and.callThrough()允许两种规范中的LogMeIn的执行,或移动间谍为点击spec这里也不会影响逻辑规范。

相关问题