2017-05-30 94 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這裏也不會影響邏輯規範。

相關問題