【问题标题】:How to mock results from uibmodal?如何模拟 uibmodal 的结果?
【发布时间】:2017-11-18 01:44:20
【问题描述】:

我有以下代码:

vm.data = [{name: 'test-1'},{name: 'test-2'}];

function addRecords(data) {
    vm.data.push(data);
}

function openPopup() {

    $uibModal.open({
        templateUrl: 'modal-popup/modal-popup.html',
        controller: 'ModalPopupController',
        controllerAs: 'vm',
        resolve: {
            id: _.constant('123')
        }
    }).result.then(addRecords);
}

试图模拟这个,下面是声明:

let allData = [{name: 'test-1'},{name: 'test-2'}];
let data = {name: 'test-3'};

    beforeEach(inject(function (_$q_, _$rootScope_, _$componentController_, _$uibModal_) {
        $q = _$q_;
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        controller = _$componentController_;
        $uibModal = _$uibModal_;

        spyOn($uibModal, 'open').and.returnValue({
            result: function() {
                return $q.when(data);
            }
        });

        vm = controller('bvcListings', {
            $q,
            data: allData,
            $uibModal
        });

        $scope.$apply();
    }));

    describe('openPopup', function () {
        it('should add records on modal results', function () {
            vm.openPopup();
            expect($uibModal.open).toHaveBeenCalled();
        });
    });

期望是,它应该添加:{name: 'test-3'} 作为现有数组的结果。

Spy on modal open 工作正常,但在获取结果后,它没有进入 addRecords 函数。我做错了什么?

在检索结果后需要在此处进行哪些更改才能进入回调函数。

【问题讨论】:

    标签: javascript angularjs modal-dialog karma-jasmine


    【解决方案1】:

    .result.then 回调方法只有在你调用modalInstance.close 方法时才会被调用,也不要忘记从close 方法传递data 类似modalInstance.close(data)

    在继续测试之前,您需要在openPopup 函数中进行一项更改。它应该返回$uibModal.open,它基本上返回新创建的模态实例。此后,您可以轻松控制模态以在需要时调用 dismiss/close 方法。

    function openPopup() {
        vm.modalInstance = $uibModal.open({
            templateUrl: 'modal-popup/modal-popup.html',
            controller: 'ModalPopupController',
            controllerAs: 'vm',
            resolve: {
                id: _.constant('123')
            }
        });
    
       vm.modalInstance.result.then(addRecords);
    }
    

    规格

    $uibModal = _$uibModal_;
    var data = {name: 'test-3'};
    //creating fake modal which will help you to mock 
    var fakeModal = {
        result: {
            then: function(confirmCallback) {
                //Store the callbacks
                this.confirmCallBack = confirmCallback;
            }
        },
        close: function( item ) {
            //The user clicked OK on the modal dialog
            this.result.confirmCallBack( item );
        }
    };
    spyOn($uibModal, 'open').and.returnValue(fakeModal);
    
    describe('It should data to vm.data when popup closed', function () {
        it('should add records on modal results', function () {
           vm.data = [{name: 'test-1'},{name: 'test-2'}];
           let data = {name: 'test-3'};
           vm.openPopup();
           expect($uibModal.open).toHaveBeenCalled();
           vm.modalInstance.close(data);
           expect(vm.data.length).toBe(4);
           expect(vm.data[3]).toBe(data);
        });
    });
    

    注意: fakeModal 已被 this post 引用

    【讨论】:

    • TypeError: undefined is not a constructor (near '...}).result.then(addRecords);...')
    • @Mithun 你能告诉我你是如何实例化控制器实例的吗?您可能没有将 $uibModal 传递给控制器​​实例
    • 编辑了我的问题@Pankaj,请检查
    • 我曾经使用过这样的模拟,但实际上没有必要用不是承诺的东西模拟承诺,因为它大大降低了你的测试可能性。
    • @Mithun 不,你不应该注射$uibModalinstance.. 你能不能给我一个plunker?
    【解决方案2】:

    继续@Pankajs 的回答。

    这是我做的一个调整并得到了它的工作。

    function openPopup() {
        vm.modalInstance = $uibModal.open({
            templateUrl: 'modal-popup/modal-popup.html',
            controller: 'ModalPopupController',
            controllerAs: 'vm',
            resolve: {
                id: _.constant('123')
            }
        }).result.then(addRecords);
    }
    

    规格

    describe('modalpopup', function () {
        it('should add records on modal results', function () {
            vm.data = [{name: 'test-1'},{name: 'test-2'}];
            let data = {name: 'test-3'};
            vm.openPopup();
            expect($uibModal.open).toHaveBeenCalled();
            vm.modalInstance.close(data);
            expect(vm.data.length).toBe(4);
            expect(vm.data[3]).toBe(data);
        });
    });
    

    对我来说就像魅力一样。我也考虑 Pankajs 的回答,几乎 90% 都解决了我的问题。

    【讨论】:

    • 我还是不明白,到底哪里发生了调整??
    • 不会 vm.data[3] 是出站异常。 vm.data[2] 会指向它
    【解决方案3】:

    添加 $rootScope.$digest(); 以解决承诺(如 $q.when())

    vm.openPopup();
    expect($uibModal.open).toHaveBeenCalled();
    $rootScope.$digest(); >> triggers your callback
    

    【讨论】:

    • 这怎么会调用result.then打开模态的方法?
    • 看看他的模拟:spyOn($uibModal, 'open').and.returnValue({ result: function() { return $q.when(data); } });
    • 那么它应该是and.returnValue({ result: { then: {function() { return $q.when(data); } }}); 再次回到我提供的模拟:p
    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    相关资源
    最近更新 更多