需要帮助完成 angular $modal 的单元测试

Need help completing unit test for angular $modal

我正在尝试让我的代码中的 "make sure modalInstance.result.then is executed" 测试通过。现在它说 Expected [ undefined, 'http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com' ] to contain 'http://www.pressboardmedia.com' 我相信这与需要被嘲笑的承诺有关,所以它通过 campaignLink 但我不确定这是否是问题所在并且似乎无法让它工作。如果您有任何想法,请告诉我们。

谢谢!

控制器文件

angular.module('pb.campaignLinks.controllers')
    .controller('CampaignLinksController', ['$scope', '$timeout', '$modal', '$stateParams', 'global', 'campaignLinkService', function ($scope, $timeout, $modal, $stateParams, global, campaignLinkService) {

        $scope.init = function (currentView) {
            $scope.partialViews = {
                campaignLinkList: "/app/campaignLinks/views/_list.html",
            };
            $scope.currentView = currentView;
            $scope.getCampaignLinks(currentView, 10);
        };

        $scope.getCampaignLinks = function (currentView, length, continuationToken) {
            // When loading list items, display loading image
            if ($scope.campaignLinks) $scope.campaignLinks.loading = true;
            var promiseObj = null;
            if (currentView.campaignId && currentView.campaignId !== 0 && !currentView.buyRequestId) {
                promiseObj = campaignLinkService.getCampaignLinks(global.activeOrganizationId, currentView.campaignId, length, continuationToken)
            } else if (currentView.campaignId && currentView.buyRequestId && currentView.campaignId !== 0 && currentView.buyRequestId !== '') {
                promiseObj = campaignLinkService.getCampaignBuyRequestLinks(global.activeOrganizationId, currentView.campaignId, currentView.buyRequestId, length, continuationToken);
            } else if (currentView.webSiteId && currentView.buyRequestId && currentView.webSiteId !== 0 && currentView.buyRequestId !== '') {
                promiseObj = campaignLinkService.getWebSiteBuyRequestLinks(global.activeOrganizationId, currentView.webSiteId, currentView.buyRequestId, length, continuationToken);
            } 

            if (promiseObj) {
                promiseObj.then(function (data) {
                    // If there are already some campaign links being displayed, add newly loaded list to the end
                    if ($scope.campaignLinks) {
                        $scope.campaignLinks.continuationToken = data.continuationToken;
                        $scope.campaignLinks.total += data.total;
                        $.each(data.items, function (index) {
                            $scope.campaignLinks.items.push(data.items[index]);
                        });
                    } else {
                        // Otherwise add loaded list to scope
                        $scope.campaignLinks = data;
                    }
                    // When done loading, hide loading image
                    $scope.campaignLinks.loading = false;
                });
            }
        };

        $scope.openAddCampaignLink = function (campaignId) {

            var modalOptions = {
                templateUrl: '/app/campaignLinks/views/_add.html',
                controller: 'AddCampaignLinksModalController',
                resolve: {
                    campaignId: function () {
                        return campaignId;
                    }
                }
            };

            var modalInstance = $modal.open(modalOptions);

            modalInstance.result.then(function (campaignLink) {
                // Add new item to list, otherwise wait for it to be loaded manually.
                $scope.campaignLinks.items.unshift(campaignLink);
                $scope.campaignLinks.total += 1;
            }, function () {
                console.log('Modal dismissed at: ' + new Date());
            });
        };

        $scope.openRemoveCampaignLink = function (campaignId, campaignLink, index) {

            var modalOptions = {
                templateUrl: '/app/campaignLinks/views/_delete.html',
                controller: 'RemoveCampaignLinksModalController',
                resolve: {
                    campaignId: function () {
                        return campaignId;
                    },
                    campaignLink: function () {
                        return campaignLink;
                    }
                }
            };

            var modalInstance = $modal.open(modalOptions);

            modalInstance.result.then(function () {
                // Splice the deleted item from the list without reloading all
                $scope.campaignLinks.items.splice(index, 1);
                $scope.campaignLinks.total -= 1;
            }, function () {
                console.log('Modal dismissed at: ' + new Date());
            });
        };

        // Once everything is loaded, initialize controller
        // init();

    }]);

测试文件:

describe('CampaignLinksController', function () {

    //make module avalible to tests
    beforeEach(module('pb.campaignLinks.controllers'));
    beforeEach(module('ui.router'));
    beforeEach(module('ui.bootstrap'));

    var $controller;
    var mockPromiseObj;
    var length = 200;
    var mockModal = {};
    var mockCampaignLinks = {
        total: 3,
        items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
    };
    var mockCurrentView = {};
    var mockGlobal = { activeOrganizationId: 54 };
    var continuationToken = {
        nextRowKey: 'fdsf2',
        nextPartitionKey: '5432gee'
    };

    var campaignDetails = {
        campaignId: 453,
        campaignLink: 'http://www.pressboardmedia.com',
        index: 1
    };

    var mockCampaignLinkService = {
        //move campaignDetails here
        campaignLinks: {
            total: 3,
            //length here
            items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
        },
        //all but delete must return a promiseObj
        getCampaignLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignLinks').and.returnValue(mockPromiseObj),
        getCampaignBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignBuyRequestLinks').and.returnValue(mockPromiseObj),
        getWebSiteBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getWebSiteBuyRequestLinks').and.returnValue(mockPromiseObj),
        deleteCampaignLink: jasmine.createSpy('mockCampaignLinkService.deleteCampaignLinks')
    };


    beforeEach(inject(function (_$controller_) {
        $controller = _$controller_;
    }));

    beforeEach(inject(function ($rootScope) {

        controller = $controller('CampaignLinksController',
            {
                $scope: scope,
                $modal: mockModal,
                //$stateParams: mockStateParams,
                global: mockGlobal,
                campaignLinks: mockCampaignLinks,
                campaignLinkService: mockCampaignLinkService,
                currentVeiw: mockCurrentView,
                //promiseObj: mockPromiseObj 
            });
    }));


    describe('openAddCampaignLink()', function () {
        var actualOptions;
        var modalOptions = {
            templateUrl: '/app/campaignLinks/views/_add.html',
            controller: 'AddCampaignLinksModalController',
            resolve: {
                campaignId: jasmine.any(Function)
            }
        };

        beforeEach(inject(function ($q) {
            mockModal.open = function (options) {
                actualOptions = options;
                var defer = $q.defer();
                defer.resolve();
                return { result: defer.promise };
            }
        }));


        it("make sure modalInstance.result.then is executed", function () {
        scope.campaignLinks = mockCampaignLinkService.campaignLinks;
        scope.openAddCampaignLink(campaignDetails.campaignId, campaignDetails.campaignLink, campaignDetails.index);
        scope.$digest();

        expect(scope.campaignLinks.total).toEqual(4);
        expect(scope.campaignLinks.items).toContain(campaignDetails.campaignLink);
    });

 });

我认为你的问题是当你测试这个时,提供给你的 modalInstance.result.then 函数的参数 "campaignLink" 总是未定义的。应测试调用模式关闭的代码是否正确提供了 campaignLink。您只想测试在模式关闭时是否执行了正确的代码。我们通过向 modalInstance.result.then 调用提供一个可以自行测试的函数来实现这一点,而不是执行内联函数,因此可以更轻松地对其进行测试。

这是一个例子:

这是打开模式的代码:

$scope.editGradeClick = function () {
        var modalInstance = $modal.open({
            templateUrl: templateSrv.templateUrl('/Templates/App/Courses/CourseLessonGradeModal.html'),
            controller: courseLessonGradeModalBootstrap,
            backdrop: 'static',
            keyboard: false,
            resolve: {
                data: $scope.editGradeModalResolve
            }
        });

        modalInstance.result.then(
            null,
            $scope.editGradeModalDismissCallback
        );
    };

注意我们如何提供一个函数 $scope.editGradeModalDismissCallback 而不是在那里编写一个内联函数来进行模式关闭。这允许我们在它自己的测试中测试该逻辑。

下面是测试。我们只关心上面的函数是否被调用,因为我们将在它自己的测试中测试特定的函数。这发生在测试的最后一行。

var $controllerConstructor, $scope, $q;

beforeEach(function () {
        module('appModule');
        inject(function ($controller, $rootScope, _$q_) {
            $controllerConstructor = $controller;
            $scope = $rootScope.$new();
            $q = _$q_;
        });
    });

it('should execute $scope.editGradeModalDismissCallback when modal is dismissed', inject(function (templateSrv) {
        var $modal = {};
        $modal.open = function () {
            var queryPromise = $q.defer();
            queryPromise.reject();

            return { result: queryPromise.promise };
        };

        $controllerConstructor('CourseLessonGradeListCtrl', { $scope: $scope, $modal: $modal, templateSrv: templateSrv});

        spyOn($modal, "open").andCallThrough();
        spyOn($scope, "editGradeModalDismissCallback");
        $scope.editGradeClick();
        $scope.$root.$digest();

        expect($scope.editGradeModalDismissCallback).toHaveBeenCalled();
    }));

希望对您有所帮助。在这个例子中,我们拒绝了承诺,因为我们正在测试模态解除未关闭,仅供参考...