Unit testing angular-bootstrap $modal

后端 未结 4 1432
感动是毒
感动是毒 2020-12-29 00:35

I\'m having problems trying to write a jasmine unit test for an Angular-Bootstrap $modal. The exact error is Expected spy open to have been called with [

相关标签:
4条回答
  • 2020-12-29 01:02

    Try this:

    describe('W2History controller', function () {
            var controller, scope, modal;
    
            var fakeModal = {
                result: {
                    then: function (confirmCallback, cancelCallback) {
                        //Store the callbacks for later when the user clicks on the OK or Cancel button of the dialog
                        this.confirmCallBack = confirmCallback;
                        this.cancelCallback = cancelCallback;
                    }
                },
                close: function (item) {
                    //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
                    this.result.confirmCallBack(item);
                },
                dismiss: function (type) {
                    //The user clicked cancel on the modal dialog, call the stored cancel callback
                    this.result.cancelCallback(type);
                }
            };
    
            var modalOptions = {
                templateUrl: '/n/views/consent.html',
                controller: 'W2ConsentModal as w2modal',
                resolve: {
                    employee: jasmine.any(Function)
                },
                size: 'lg'
            };
    
            var actualOptions;
    
            beforeEach(function () {
                module('plunker');
    
                inject(function (_$controller_, _$rootScope_, _$modal_) {
                    scope = _$rootScope_.$new();                         
                    modal = _$modal_;
    
                    spyOn(modal, 'open').and.callFake(function(options){
                        actualOptions = options;
    
                        return fakeModal;
                    });
    
                    controller = _$controller_('W2History', {
                        $scope: scope,
                        $modal: modal
                    });
    
                });
    
            });
    
            it('Should correctly show the W2 consent modal', function () {
                var employee = { name : "test"};
    
                controller.showModal(employee);
                expect(modal.open).toHaveBeenCalledWith(modalOptions);
                expect(actualOptions.resolve.employee()).toEqual(employee);
            });
        });
    

    PLUNK

    Explanation:

    We should not expect the actual resolve.employee to be the same with the fake resolve.employee because resolve.employee is a function which returns an employee (in this case the employee is captured in closure). The function could be the same but at runtime the returned objects could be different.

    The reason your test is failing is the way javascript compares functions. Take a look at this fiddle. Anyway, I don't care about this because we should not expect function implementations. What we do care about in this case is the resolve.employee returns the same object as we pass in:

    expect(actualOptions.resolve.employee()).toEqual(employee);
    

    So the solution here is: We expect everything except for the resolve.employee:

    var modalOptions = {
                    templateUrl: '/n/views/consent.html',
                    controller: 'W2ConsentModal as w2modal',
                    resolve: {
                        employee: jasmine.any(Function) //don't care about the function as we check it separately.
                    },
                    size: 'lg'
                };
    
       expect(modal.open).toHaveBeenCalledWith(modalOptions);
    

    Check the resolve.employee separately by capturing it first:

    var actualOptions;
    
     spyOn(modal, 'open').and.callFake(function(options){
          actualOptions = options; //capture the actual options               
          return fakeModal;
     });
    
    expect(actualOptions.resolve.employee()).toEqual(employee); //Check the returned employee is actually the one we pass in.
    
    0 讨论(0)
  • 2020-12-29 01:06

    I am not sure if this will help you now, but when you spy on something you can get the argument that is passed to the $uibModal.open spy, you can then call that function to test that it returns what is in the resolve method.

    it('expect resolve to be have metadataid that will return 9999', () => {
                spyOn($uibModal, 'open');
                //add test code here that will call the $uibModal.open
                var spy = <jasmine.Spy>$uibModal.open;
                var args = spy.calls.argsFor(0);
                expect(args[0].resolve.metadataId()).toEqual(9999);
    });
    

    ***** my code is using typescript, but this works for me.**

    0 讨论(0)
  • 2020-12-29 01:09

    This is a pass by reference vs pass by value issue. The resolve.employee anonymous function used in $modal.open:

    var modalInstance = $modal.open({
        templateUrl: '/n/views/consent.html',
        controller: 'W2ConsentModal as w2modal',
        resolve: {
            employee: function () {
                return employee;
            }
        },
        size: 'lg'
    });
    

    is not the same (by reference) as the resolve.employee anonymous function in your test:

    var modalOptions = {
        templateUrl: '/n/views/consent.html',
        controller: 'W2ConsentModal as w2modal',
        resolve: {
            employee: function () {
                return employee;
            }
        },
        size: 'lg'
    };
    

    Your test should be:

    resolve: {
        employee: jasmine.any(Function)
    }
    

    If it's essential that the resolve function be tested, you should expose it somewhere where you can get a reference to the same function in your tests.

    0 讨论(0)
  • 2020-12-29 01:20

    I have come across the same scenario. I have come across the problem with the below given solution

    //Function to open export modal
    scope.openExportModal();
    expect( uibModal.open ).toHaveBeenCalledWith(options);
    expect( uibModal.open.calls.mostRecent().args[0].resolve.modalData() ).toEqual(modalData);
    

    Hope this may help if you want a quick fix.

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