Unit testing a modalInstance controller with Karma / Jasmine

大兔子大兔子 提交于 2019-11-28 16:06:54

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.

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"

+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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!