Unit testing a modalInstance controller with Karma / Jasmine

后端 未结 3 1979
故里飘歌
故里飘歌 2020-12-12 18:09

EDIT : Quick & Dirty solution at the end of this post

I am using a modal window from AngularUI-Bootstrap in the same way that it is explained on

相关标签:
3条回答
  • 2020-12-12 19:09

    Instead of:

    modalInstance = {                    // Create a mock object using spies
      close: jasmine.createSpy('modalInstance.close'),
      dismiss: jasmine.createSpy('modalInstance.dismiss'),
      result: {
        then: jasmine.createSpy('modalInstance.result.then')
      }
    };

    This can be written as:

    modalInstance = jasmine.createSpyObj('modalInstance', ['close', 'dismiss', 'result.then']);

    Also there is no $modalInstance it is now $uibModalInstance so every "modalInstance" above should be replaced with "uibModalInstance"

    0 讨论(0)
  • 2020-12-12 19:10

    I am solving this by just creating mock modal and modalInstance objects and verifying that they have been called by my controller code. Since modal and modalInstance are part of a third party library, it's not our responsibility to test that they work properly - rather, it's our responsibility to test that our code which calls the library is working ok.

    Using your example:

    describe('Controller: modalCtrl', function () {
    
      beforeEach(module('myApp'));
    
      var Ctrl;
      var scope;
      var modalInstance;
    
      // Initialize the controller and a mock scope
      beforeEach(inject(
        function ($controller, $rootScope) {     // Don't bother injecting a 'real' modal
          scope = $rootScope.$new();
          modalInstance = {                    // Create a mock object using spies
            close: jasmine.createSpy('modalInstance.close'),
            dismiss: jasmine.createSpy('modalInstance.dismiss'),
            result: {
              then: jasmine.createSpy('modalInstance.result.then')
            }
          };
          Ctrl = $controller('modalCtrl', {
            $scope: scope,
            $modalInstance: modalInstance,
            itemArray: function () { return ['a', 'b', 'c']; }
          });
        })
      );
    
      describe('Initial state', function () {
        it('should instantiate the controller properly', function () {
          expect(Ctrl).not.toBeUndefined();
        });
    
        it('should close the modal with result "true" when accepted', function () {
          scope.accept();
          expect(modalInstance.close).toHaveBeenCalledWith(true);
        });
    
        it('should close the modal with result "false" when rejected', function () {
          scope.reject();
          expect(modalInstance.close).toHaveBeenCalledWith(false);
        });
      });
    });
    

    This way, we don't really need any dependency on the Angular-UI objects and our unit tests are nice and isolated.

    0 讨论(0)
  • 2020-12-12 19:11

    +1 for fiznool's answer. it is correct and should be chosen..

    I would like to note one thing though, it is not maintainable the way it is presented here.

    Since this is angular, I suggest use it..

    angular.module('...').service('$modalInstance', function(){
       ... define spies and such 
    })
    

    would make your code much more modular and generic. simply add a file under spec somewhere with the above content and make sure to include it in your karma.conf

    if you want to make sure it loads only in specific tests, simply give it a unique module name and add it to module invocation in beforeEach

    0 讨论(0)
提交回复
热议问题