8

我想寫一個單元測試,驗證$rootScope.$broadcast('myApiPlay', { action : 'play' });被調用。

這裏是myapi.js

angular.module('myApp').factory('MyApi', function ($rootScope) { 
    var api = {}; 
    api.play = function() { 
     $rootScope.$broadcast('myApiPlay', { action : 'play' }); 
    } 
    return api; 
}); 

這裏是我的單元測試:

describe('Service: MyApi', function() { 

    // load the service's module 
    beforeEach(module('myApp')); 

    // instantiate service 
    var MyApi; 
    var rootScope; 

    beforeEach(function() { 
     inject(function ($rootScope, _MyApi_) { 
      MyApi = _MyApi_; 
      rootScope = $rootScope.$new(); 
     }) 
    }); 
    it('should broadcast to play', function() { 
     spyOn(rootScope, '$broadcast').andCallThrough(); 
     rootScope.$on('myApiPlay', function (event, data) { 
      expect(data.action).toBe('play'); 
     }); 
     MyApi.play(); 
     expect(rootScope.$broadcast).toHaveBeenCalledWith('myApiPlay'); 
    }); 
}); 

這是在運行grunt test我得到的錯誤:

PhantomJS 1.9.7 (Windows 7) Service: MyApi should broadcast to pause FAILED 
     Expected spy $broadcast to have been called with [ 'myApiPlay' ] but it was never called. 

我也試過expect(rootScope.$broadcast).toHaveBeenCalled(),我有類似的錯誤:Expected spy $broadcast to have been called.

我想驗證該方法實際上是用正確的參數調用的。

謝謝!

+0

你只需要切換順序?您可能需要在實際調用之前預期,在您調用它的情況下,然後期待它。你也可以確認通話計數。 – hassassin 2014-09-12 22:12:56

+0

我改變了順序,同樣的錯誤。 – Andrea 2014-09-12 22:25:49

回答

14

你的測試不及格的原因是因爲你在錯誤的$廣播功能刺探。在你的beforeEach設置中,你要求注入$ rootScope,然後通過調用$ rootScope。$ new()來創建一個子範圍。

$ rootScope。$ new()的返回值不再是rootScope,而是根作用域的子對象。

beforeEach(function() { 
    //inject $rootScope 
    inject(function ($rootScope, _MyApi_) { 
     MyApi = _MyApi_; 
     //create a new child scope and call it root scope 
     rootScope = $rootScope.$new(); 
     //instead don't create a child scope and keep a reference to the actual rootScope 
     rootScope = $rootScope; 
    }) 
}); 

在您的播放功能,你呼籲$ rootScope $播出,但在測試你刺探$ rootScope的孩子。

$rootScope.$broadcast('myApiPlay', { action : 'play' }); 

所以把它包起來,取出調用$ rootScope。美元的新(),只是刺探$ rootScope注射器給你。提供給您的單元測試的$ rootScope與提供給您的API服務的$ rootScope相同,因此您應該直接在$ rootScope上進行間諜。

退房的plunkr http://plnkr.co/edit/wN0m8no2FlKf3BZKjC4k?p=preview

+2

這對'expect(rootScope。$ broadcast).toHaveBeenCalledWith('myApiPlay',{action:'play'})'很好,'但是這個期望不叫:'rootScope。$ on('myApiPlay',function(event ,data){expect(data.action).toBe('play');});' – Andrea 2014-09-12 23:06:28

+1

你不需要那個測試。該測試正在測試角度框架,而不是業務邏輯本身。您可以假設,當您調用rootScope。$ broadcast時,使用$ on的監聽器設置將被正確調用,因爲這就是AngularJS的工作原理 – jcruz 2014-09-12 23:17:46

+0

您真正需要測試的是$ rootScope。$廣播被稱爲預期參數 – jcruz 2014-09-12 23:19:02

1

它對您有幫助https://stackoverflow.com/a/17227264/2594499 您的測試尚不清楚。避免在條件,回調和這樣的事情中使用「期望」。 如果你的情況不是真的,你沒有斷言測試。

這將是更好地使用功能的第二個參數:

.toHaveBeenCalledwith('someEvent', someObj); 
+0

你好,我像你說的那樣做,但是單元測試說它沒有被調用。我正在測試,當調用MyApi.play()時,廣播消息。 – Andrea 2014-09-12 22:41:05

相關問題