angular-ui/bootstrap: Testing a controller that uses a dialog

跟風遠走 提交于 2019-12-06 12:15:52

Personally I try to mock all services out. If the ui-bootstrap project does not provide a $dialog mock, you should open a bug ticket there and ask them for one. However creating one is as easy.

The mock service should have fake methods that do nothing but return promises. It should also give you a method to flush all asynchronous methods to make it easier to do synchronous testing.

I was struggling with the same problem until right now, after trolling the the github repo i found the dialog tests and used that as a starting point :

var $dialog,$scope,$httpBackend;
  beforeEach(module('ui.bootstrap.dialog'));
  beforeEach(function(){
    inject(function (_$dialog_, _$httpBackend_, $controller){
      $dialog = _$dialog_;
      $httpBackend = _$httpBackend_;
      $httpBackend.expectGET('/appServer/list')
        .respond([{
            id:1,
            name:'test1'
          },
          {
            id:2,
            name:'test2'
          },
          {
            id:3,
            name:'test3'
          }]);


      //setup controller scope
      scope = {};
      ServerCtrl = $controller('ServerCtrl', {
        $scope: scope,
        $dialog:$dialog
      });
    });
  });

I also prefer a proper mock. When it is not available, i patch the service

To test this:

$dialog.messageBox(title, msg, btns)
   .open()
   .then(function (result) {
       if (result == 'ok') {
            // block executed if user click OK
       }
});

You can patch $dialog like this:

$dialog.messageBox = function (title, msg, btns) {
    return {
        open: function () {
            return {
                 then: function (callback) {
                      callback('ok'); // 'ok' will be set to param result
                 }
             }
        }
    }
 };

I find it clearest to write my own mock of the dialog. Here's an example of mocking out a dialog to simulate "yes" being chosen.

Code under test

.controller('AdminListingCtrl', function AdminListingController($scope, $dialog, houseRepository) {
    $scope.houses = houseRepository.query();
    $scope.remove = function (house) {
        var dlg = $dialog.messageBox('Delete house', 'Are you sure?', [
            {label: 'Yep', result: 'yes'},
            {label: 'Nope', result: 'no'}
        ]);
        dlg.open().then(function (result) {
            if (result == 'yes') {
                houseRepository.remove(house.id);
                $scope.houses = houseRepository.query();
            }
        });
    };
}

Tests

    describe('when deleting a house', function () {

        var fakeDialog = {
            open: function()
            {
                return {
                    then: function(callback) {
                        callback("yes");
                    }
                };
            }
        };

        beforeEach(inject(function($dialog) {
            spyOn($dialog, 'messageBox').andReturn(fakeDialog);
        }));

        it('should call the remove method on the houseRepository', function () {
            scope.remove({id: 99});
            expect(houseRepository.remove).toHaveBeenCalledWith(99);
        });

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