测试使用$ emit发出的角度事件

时间:2015-09-17 11:47:11

标签: angularjs jasmine

我正在尝试使用茉莉花间谍来测试$emit发出的角度事件。

以下测试:

describe('DashboardCtrl', function () {
    var scope, httpBackend, domainService;
    beforeEach(module('bignibou', 'dashboard', 'utils'));
    beforeEach(inject(function ($controller, $rootScope, _domainService_, messageService, $httpBackend) {
        domainService = _domainService_;
        scope = $rootScope.$new();
        $controller('DashboardCtrl', {
            $scope: scope,
            domainService: domainService,
            messageService: messageService,
            currentUserAccount: {data: {firstName: 'John'}},
            unreadMessagesCount: 0,
            latestMessages: []
        });
        spyOn(scope, '$emit');
        spyOn(scope, '$on');
        spyOn(domainService, 'currentUserAccount').and.returnValue(function () {
            var deferred = $q.defer();
            deferred.resolve({id: 42, firstName: 'Pedro'});
            return deferred.promise;
        });
        httpBackend = $httpBackend;
        httpBackend.whenGET('/api/utils/current-useraccount').respond({id: 42, firstName: 'Pedro'});
    }));
    it('should handle user account updated', function () {
        scope.$emit('useraccount:updated');
        expect(scope.$on).toHaveBeenCalled();
        expect(domainService.currentUserAccount).toHaveBeenCalled();
        expect(scope.currentUserAccount.firstName).toEqual('Pedro');
    });
});

的产率:

PhantomJS 1.9.8 (Mac OS X 0.0.0) DashboardCtrl should handle user account updated FAILED
        TypeError: 'undefined' is not an object (evaluating 'spyOn(domainService, 'currentUserAccount').and.returnValue')
            at /Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/test/unit/dashboard.spec.js:17
            at invoke (/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/src/bower_components/angular/angular.js:4473)
            at workFn (/Users/julien/Documents/projects/bignibou/bignibou-site/bignibou-client/src/bower_components/angular-mocks/angular-mocks.js:2426)
        undefined
        Expected spy $on to have been called.
        Expected spy currentUserAccount to have been called.
        Expected 'John' to equal 'Pedro'.
PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.005 secs / 0.034 secs)

来自我的域名服务:

currentUserAccount: function () {
    return $http.get('/api/utils/current-useraccount', {
        cache: false
    });
},

来自DashboardCtrl:

$scope.$on('useraccount:updated', function () {
    domainService.currentUserAccount().success(function (data) {
        $scope.currentUserAccount = data;
    });
});

我不确定自己错了什么。任何人都可以告诉我为什么不调用$on监听器功能?

3 个答案:

答案 0 :(得分:1)

在调用spyOn(scope, '$on')之前需要$controller,因为在控制器构造函数中调用了$on。但是既然你想窥探听众,你可以这样做:

  $controller('DashboardCtrl', ...);
  listeners = scope.$$listeners['useraccount:updated'];
  spyOn(listeners, 0);

it

  scope.$emit('useraccount:updated');
  expect(listeners[0]).toHaveBeenCalled();

答案 1 :(得分:0)

正如您所见,$ scope。$ on函数有两个参数:

  • 您要订阅的事件
  • 触发事件时要执行的功能

这意味着$ scope。$ on会在Controller初始化时调用,而不是在事件发出时调用。

因此,如果您想检查您的函数是否被调用,您可以执行以下操作:

  1. 将您的函数添加到$ scope(或变量)

    $ scope.update = function(){     domainService.currentUserAccount()。success(function(data){         $ scope.currentUserAccount = data;     }); }

  2. 列出项目

    $ scope。$ on('useraccount:updated',$ scope.update);

  3. 修改你的测试:

    spyOn($ scope,'update'); 期望(scope.update).toHaveBeenCalled();

  4. 希望这是有道理的

答案 2 :(得分:0)

我意识到我的测试实际上不需要任何茉莉花间谍。

我只想确保在$scope上设置正确的值,如下所示:

describe('DashboardCtrl', function () {
    var scope, httpBackend;
    beforeEach(module('bignibou', 'dashboard', 'utils'));
    beforeEach(inject(function ($controller, $rootScope, domainService, messageService, $httpBackend) {
        scope = $rootScope.$new();
        $controller('DashboardCtrl', {
            $scope: scope,
            domainService: domainService,
            messageService: messageService,
            currentUserAccount: {data: {firstName: 'John'}},
            unreadMessagesCount: 0,
            latestMessages: []
        });

        httpBackend = $httpBackend;

        //TODO: do I need all those expectations?
        httpBackend.whenGET('/api/utils/signup-roles').respond({});
        httpBackend.whenGET('/api/utils/parents-needs').respond({});
        httpBackend.whenGET('/api/utils/childcare-worker-types').respond({});
        httpBackend.whenGET('/api/utils/childcare-types').respond({});
        httpBackend.whenGET('/api/utils/all-day-to-time-slots').respond({});
        httpBackend.whenGET('/api/utils/regular-day-to-time-slots').respond({});
        httpBackend.whenGET('/info').respond({build: {version: '1.0'}});
        httpBackend.whenGET(/app.+/).respond({});

        httpBackend.whenGET('/api/utils/current-useraccount').respond({id: 42, firstName: 'Pedro'});
    }));
    it('should handle user account updated', function () {
        scope.$emit('useraccount:updated');
        httpBackend.flush();
        expect(scope.currentUserAccount.firstName).toEqual('Pedro');
    });
});

请注意,我现在拨打flush()

上面的测试有效,但不是很干净,因为我需要为httpBackend提供所有出色的期望......

我猜这是另一个问题。