【问题标题】:Angular unit testing service element persistenceAngular 单元测试服务元素持久化
【发布时间】:2015-02-09 06:29:29
【问题描述】:

我目前正在编写一个服务来控制上传流程。我现在正在为显示和隐藏上传模式框的功能编写单元测试。在测试中,我使用angular.element.find 来查看模态是否存在。在第二个测试中,这个数字比我预期的要高,好像它没有重置一样。

两个测试如下:

    describe('show', function() {
        it('should initially not show the modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);
        });

        it('should show the upload modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);
        });
    });

    describe('cancel', function() {
        it('should hide the upload form', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);

        });
    });

第一个描述块通过正常,但第二个失败。它告诉我它Expected 1 to equal 0. 如果我在cancel 的测试中用angular.element.find 注释掉第一个期望,它会说“期望2 等于1。”

我所能确定的是,html 都被扔进了同一个空间,并且在每次测试后都在复合。有什么方法可以防止这种行为,或者使用 `afterEach' 语句来刷新以前的 HTML?

谢谢!


修正

如果有帮助,这里是这套测试的完整代码:

describe('uploadService', function() {
    var $rootScope,
        upload;

    beforeEach(module('upload'));
    beforeEach(module('upload.service'));
    beforeEach(module('bublNg.templates'));
    beforeEach(module('ui.bootstrap.tpls'));

    beforeEach(inject(function($injector) {
        upload = $injector.get('upload');
        $rootScope = $injector.get('$rootScope');
    }));

    describe('isShowing', function() {
        it('should return true if the modal us showing', function() {
            expect(upload.isShowing()).toEqual(false);

            upload.show();
            expect(upload.isShowing()).toEqual(true);
        });
    });

    describe('show', function() {
        it('should initially not show the modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);
        });

        it('should show the upload modal', function() {
            expect(upload.isShowing()).toEqual(false);
            expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            expect(angular.element.find('.modal').length).toEqual(1);
        });
    });

    describe('cancel', function() {
        it('should hide the upload form', function() {
            expect(upload.isShowing()).toEqual(false);
            // expect(angular.element.find('.modal').length).toEqual(0);

            upload.show();
            $rootScope.$digest();
            expect(upload.isShowing()).toEqual(true);
            // expect(angular.element.find('.modal').length).toEqual(1);
            upload.cancel();
            expect(upload.isShowing()).toEqual(false);

        });
    });
});

【问题讨论】:

    标签: javascript angularjs unit-testing angular-ui-bootstrap angularjs-service


    【解决方案1】:

    避免测试 html 元素是否存在这样的事情。当您使用 UI Bootstrap 时,您应该将 $modal 服务注入您的测试并监视其 open 方法。然后测试你的代码对它的调用。这可以防止测试期间的 DOM 污染。

    这个模式应该让你开始:

    var $modal;
    
    beforeEach(inject(function($injector) {
        $modal = $injector.get('$modal');
    }));
    
    beforeEach(function() {
        spyOn($modal, 'open');
        // or, to mock/fake a modal object so you can test close/dismiss handlers
        // spyOn($modal, 'open').and.returnValue(mockModal);
        // see: http://stackoverflow.com/a/21370703/2943490
    });
    
    describe('show', function() {
        it('should initially not show the modal', function() {
            expect($modal.open).not.toHaveBeenCalled();
        });
    
        it('should show the upload modal', function() {
            upload.show();
            $rootScope.$digest();
    
            expect($modal.open).toHaveBeenCalledWith({
                // your modal options
            });
        });
    });
    

    【讨论】:

    • 谢谢!一个很好的方法,绝对。我没有想过监视模式服务本身,但这是完全有道理的。我会改用这种方法。出于好奇,你知道我为什么会得到这样的结果吗?测试之间是否有一些未清除的内容?
    • @Octothorpe,您的第一个观察结果是正确的:“我所能确定的是,html 都被扔进了同一个空间,并且在每次测试后都在复合。”通过在 afterEach 中搜索 .modal 并删除它,你可以解决这个问题,但你不必通过监视 $modal.open 来麻烦自己。另请注意,$modal 保留了已打开模式的内部寄存器,因此仅将它们从 DOM 中删除并不能真正清理干净。
    • 好的,很高兴知道。我仍然有很多东西要了解很多这样的事情。感谢您的确认!
    【解决方案2】:

    现在您可能会将用于设置测试的代码放在文件的开头。尝试将其放在 beforeEach 语句中。

    【讨论】:

    • 刚刚添加了单元测试的完整代码。让我知道这是否有助于澄清任何事情。我不是 100% 确定你的意思。
    猜你喜欢
    • 2019-05-06
    • 2017-06-03
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多