1

我有一個方法和服務的組件,它可以運行一些組件的功能。如何測試Ember.js中的組件方法?

export default Ember.Component.extend({ 
    foo: false, 

    bar() { 
    this.set('foo', true); 
    }, 

    someService: Ember.inject.service('some-service'), 

    didInsertElement: function() { 
    const someService = this.get('someService'); 
    someService.registerComponent(this); 
    }, 
}); 

export default Ember.Service.extend({ 
    components: [], 
    registerComponent: function (component) { 
    let components = this.get('components'); 
    components.push(component); 
    }, 
    runBar(index) { 
    let components = this.get('components'); 
    components[index].bar(); 
    } 
}); 

1)如何爲bar()方法編寫測試?

2)還有我該如何編寫這項服務的測試?

3)或者我該如何重構這種方法?

+0

還有什麼我可以幫助你這個或你不喜歡我的答案的任何部分? – alptugd

回答

3

我會盡量按順序回答你的問題;在開始之前,請查看以下twiddle我已經準備好了。我剛剛複製了你的組件和服務定義;還爲該組件添加了willDestroyElement,併爲該服務添加了unregisterComponent以進行必要的清理以從該服務中刪除該組件。請注意清理工作;如果你完全不考慮,你會遇到很大的麻煩。關於你的問題;

1)您不得直接調用bar方法進行組件測試。你需要做的是渲染組件;檢查一些斷言;並調用服務的方法runBar,以便在集成測試中調用組件的bar方法。據我所知,這是你心目中的情景。請在我上面提供的旋轉中查看my-component-test.js文件。在這個測試中的關鍵部分可能是

Ember.run(()=>Ember.getOwner(this).lookup('service:some-service').runBar(0)); 

代碼片段。 Ember.getOwner(this).lookup()使您能夠獲取服務;請注意,您需要提供全名(service:some-service)才能獲取它。它處於運行循環中;因爲它應該有一個異步的影響,Ember警告你。無論如何;測試本身很簡單,我猜;因爲該組件所做的只是將foo屬性打印到屏幕上,並且在調用服務的runBar方法時,該屬性將從初始值false設置爲true

2)用於測試服務;你可以寫一個單元測試,這就是我在旋轉中所做的。注意;你不需要實際的組件來註冊服務;所以我使用了存根組件(在旋轉中只有Ember.Object的虛擬實例)。其餘的很容易遵循我相信。我只需調用服務的runBar方法並檢查預期的斷言。

3)現在這是一個難題;因爲從你提供的代碼片段中看到你的意圖不容易做出這樣的設計。儘管如此;我對重構的評論如下:儘可能避免將組件註冊到其他構造(父組件,子組件,控制器,路由,服務等)。恕我直言,該組件的內部功能只能由組件本身調用。組件的接口應該是由組件觸發的事件(我指的是從外部提供的動作)以及從外部傳遞的屬性。我並不是說你的設計在任何情況下都應該避免。但只有在沒有其他選項可行的情況下,才必須謹慎使用。主要原因是這樣的;用這種設計來追溯代碼應該成爲一場噩夢。任何有權訪問該服務的人都應該對組件(已註冊到該服務)進行更新,該組件對其一無所知。這是我真正不喜歡的。我的建議是依賴定義良好的API,以便不傳遞它的組件並從不相關的地方對其進行更新。

這是一篇很長的文章;我希望它有幫助。

+0

非常感謝! 我會盡快嘗試這種方法 –

+0

我的目標是創建加載微調組件,並通過微調器名稱服務從不同組件觸發動畫。 Spinner組件可以放置在應用程序的任何位置以阻止某些內容的一部分。 這就是爲什麼我不知道更好的方式來管理所有spinners狀態。 –