2015-06-10 49 views
7

我有以下控制器EditMeetingCtrl.js

(function() { 
    'use strict'; 

    angular 
     .module('myApp') 
     .controller('EditMeetingCtrl', EditMeetingCtrl); 

    EditMeetingCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$translate', 
     'meetingService', 'companyService', 'notificationService', 'meeting']; 

function EditMeetingCtrl($rootScope, $scope, $state, $http, $translate, meetingService, companyService, notificationService, meeting) { 
     $scope.meeting = meeting; 

     $scope.companyId = $state.params.companyId; 
     $scope.save = save; 


     function save() { 
      $scope.buttonDisable = true; 
      meetingService.saveMeeting($state.params.companyId, $state.params.meetingId, $scope.meeting) 
       .success(function(meetingId) { 
        //more code 
       }); 
     } 


} 
})(); 

EditMeetingCtrlSpec.js测试用例

describe('in EditMeetingCtrl', function() { 

    var companyService , meetingService ; 

    meetingId = 123321 ;      
    companyId = 456654 ; 
    meetingObj = {} ; 

    var fakeHttpPromise = { 
          success: function() {} 
          }; 

    beforeEach(angular.mock.module('myApp')); 

    beforeEach(angular.mock.inject(function (_$httpBackend_, _companyService_ , _meetingService_) { 
     $httpBackend = _$httpBackend_; 
     companyService = _companyService_; 
     meetingService = _meetingService_ ; 
    })); 

    describe('EditMeetingCtrl.save()', function() { 
     var $rootScope, scope, $controller , $q ; 

     beforeEach(inject(function ($rootScope, $controller , _meetingService_) { 
      scope = $rootScope.$new(); 
      createController = function() { 
       return $controller('EditMeetingCtrl', { 
       $scope: scope, 
       meeting : {} , 
       meetingService : _meetingService_ 
       }); 
      }; 
      var controller = new createController(); 
     })); 

     it("should save the meeting object", function() { 
      spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise); 
      scope.save(); 
      expect(meetingService.saveMeeting).toHaveBeenCalledWith(meetingId , companyId , meetingObj); 
     }); 

    }); 

}); 

当尝试运行下面的测试CASSE EditMeetingCtrlSpec .js我得到以下测试失败

PhantomJS 1.9.8 (Windows 8) EditMeetingCtrl Spying --> EditMeetingCtrl.save() should save the meeting FAILED 
     Expected spy saveMeeting to have been called with [ 123321, 456654, Object({ }) ] but actual calls were [ undef 
ined, undefined, Object({ }) ]. 

所以方式明白我的这个问题, save()方法的服务调用包含$state.params.companyId, $state.params.meetingId参数,并在服务调用被调用时发送undefined值。因此我需要嘲笑$state.params。不知道该怎么做。任何人都可以指引我正确的方向吗?

编辑后迈克尔Radionov回答

describe('EditMeetingCtrl.save()', function() { 
     var $rootScope, scope, $controller , $q , $state ; 

     beforeEach(inject(function ($rootScope, $controller , $state , _meetingService_) { 
      scope = $rootScope.$new(); 
      createController = function() { 
       return $controller('EditMeetingCtrl', { 
       $scope: scope, 
       meeting : {} , 
       meetingService : _meetingService_ 
       }); 
      }; 
      var controller = new createController(); 
     })); 

     it("should save the meeting", function() { 
      $state.params = { companyId: 123, meetingId: 567 }; 
      spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise); 
      scope.save(); 
      //expect(meetingService.saveMeeting).toHaveBeenCalledWith(meetingId , companyId , meetingObj); 
     }); 

    }); 

我已经做了上述情况,但我得到了以下错误说$状态没有定义。

Firefox 38.0.0 (Windows 8.1) In EditMeetingCtrl EditMeetingCtrl.save() should save the meeting FAILED 
     TypeError: $state is undefined in C:/Users/sal/Documents/myApp/test/meeting/EditMe 
etingCtrlSpec.js (line 80) 

我以为这事,因为我没有做到这一点 - >在注入方法$state : state,所以我尝试这样做太多,但得到了同样的错误。我在这里错过了什么?

回答

15

您可以模拟整个$state供应商,然后指定调用save前的确切值,你想在params属性:

describe('in EditMeetingCtrl', function() { 

    // ... 
    beforeEach(angular.mock.module('myApp')); 

    beforeEach(angular.mock.module(function ($provide) { 

     // mock the entire $state provider 
     $provide.provider('$state', function() { 
      return { 
       $get: function() { 
        return { 
         // by default it will be an empty object 
         params: {} 
        }; 
       } 
      }; 
     }); 

    })); 

    // .... 

    describe('EditMeetingCtrl.save()', function() { 

     // inject mocked $state - one that you've provided above 

     var $rootScope, scope, $controller, $q, state; 
     // ---------------------------------------^^^ 

     beforeEach(inject(function ($rootScope, $controller, $state, _meetingService) { 
      // ------------------------------------------------^^^ 
      state = $state; 
     })); 

     // ... 

     it("should save the meeting object", function() { 

      // provide custom params which will be used in a call 
      state.params = { companyId: 123, meetingId: 567 }; 

      spyOn(meetingService, 'saveMeeting').and.returnValue(fakeHttpPromise); 
      scope.save(); 
      expect(meetingService.saveMeeting).toHaveBeenCalledWith(meetingId , companyId , meetingObj); 
     }); 
    }); 

    // ... 

}); 
+0

感谢您的回复。请看看我在我的问题中所做的修改。 ?我做错了什么? – Malik

+1

我认为这是因为错误的变量名称。使用'var state;',然后在注入时使用'state = $ state',并在'it'块中使用'state.params'。我已经更新了我的答案,请参阅编辑链接。 –

+0

谢谢! 。这工作。现在我知道我做错了什么。:) – Malik