Jasmine - 测试函数调用变量

Jasmine - test function invoking variable

我正在尝试测试通过 angular 控制器中的局部变量调用服务方法时的场景。

在这种情况下,当项目数组为 0 时,将通过模态服务触发创建新项目模态。

控制器:

(function() {
    'use strict';

    angular
        .module('app')
        .controller('Item', Item);

    //items is resolved through the ui-router resolve
    //items contains a array of item objects. Will be an empty array if there are no items for that user

    Item.$inject = ['items', 'modalService'];

    function Item(items, modalService) {
        var vm = this;
        vm.items = items;
        vm.newItemModal = modalService.newItemModal;

        if (vm.items !== undefined) {
            if (vm.items.length === 0) {
                vm.newItemModal();
            }
        }
    }

})();

vm.newItemModal() 触发要显示的新项目模式。但是,如何在 jasmine 中测试这种情况?

目前测试:

describe('Controller: Item', function(){
    var scope, 
    ctrl, 
    items, 
    modalService,
    mockItems = [{ name: 'item1', desc:'desc1'}, { name: 'item2', desc:'desc2'}];

    //mocking the modalService
    beforeEach(function(){
        module(function($provide){
            modalService = {
                newItemModal: function(){
                    return;
                }
            };
            $provide.value('modalService', modalService);
        });

    });

    beforeEach(inject(function(_$rootScope_, $controller) {
        $rootScope = _$rootScope_;
        scope = $rootScope.$new();
        ctrl = $controller('Item as item', {
            $scope: scope,
            items: mockItems
        });
    }));

    it('should verify the vm object', function(){
        expect(scope.item.newItemModal).toBeDefined();
        expect(scope.item.items).toEqual(mockItems);
    });

    //Separate test-suite as items is initialised with an empty array
    describe('new item modal', function(){
        beforeEach(inject(function(_$rootScope_, $controller) {
        $rootScope = _$rootScope_;
        scope = $rootScope.$new();
        ctrl = $controller('Item as item', {
            $scope: scope,
            items: []
        });

        it('should open a new item modal', function(){
            //returns 0
            console.log('Items length', scope.items.length);
            spyOn(scope.item, 'newItemModal').and.callThrough();
            //testing this assertion fails
            expect(scope.item.newItemModal).toHaveBeenCalled();
        });
    }));
});
});

问题是当下面一行被执行时:

spyOn(scope.item, 'newItemModal').and.callThrough();

控制器已创建,代码已执行。

您需要在创建控制器之前设置您的间谍。

示例:

var createController;

beforeEach(inject(function(_$rootScope_, $controller) {
  $rootScope = _$rootScope_;
  scope = $rootScope.$new();

  createController = function() {
    $controller('Item as item', {
      $scope: scope,
      items: []
    });
  };
}));

it('should open a new item modal', function() {
  spyOn(modalService, 'newItemModal').and.callThrough();
  createController();
  expect(scope.item.newItemModal).toHaveBeenCalled();
});

请注意,您无法监视 scope.item,因为它在控件创建之前不会被创建,因此您将不得不监视 modalService

演示: http://plnkr.co/edit/y0vzfaqDSuuCuPVwdybq?p=preview