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

相关问题