【问题标题】:Karma-Jasmine: How to properly spy on a Modal?Karma-Jasmine:如何正确监视 Modal?
【发布时间】:2015-10-27 11:54:47
【问题描述】:

情况:

我正在对我的 Angular / Ionic 应用程序进行单元测试。

我遇到了模态问题。 目前我可以测试模态是否已被调用。到此为止。我无法测试模态的正确 show() 和 hide() 方法。

我收到以下错误:

TypeError: $scope.modal_login.show is not a function
Error: show() method does not exist

TypeError: $scope.modal_login.hide is not a function
Error: hide() method does not exist

我认为这完全取决于间谍。我不知道如何正确监视模态,我认为一旦完成,一切都会正常。

代码:

控制器:

$scope.open_login_modal = function() 
{
    var temp = $ionicModal.fromTemplateUrl('templates/login.html',{scope: $scope});

    temp.then(function(modal) { 
        $scope.modal_login = modal;
        $scope.modal_login.show();

        $scope.for_test_only = true;
    });
};

$scope.close_login_modal = function() 
{
    $scope.modal_login.hide();
};

注意:open_login_modal函数的代码已经重构,方便测试。原来的代码是:

$scope.open_login_modal = function() 
{
    $ionicModal.fromTemplateUrl('templates/login.html', {
        scope: $scope
    }).then(function(modal) {

        $scope.modal_login = modal;
        $scope.modal_login.show();
    }); 
};

测试:

describe('App tests', function() 
{
    beforeEach(module('my_app.controllers'));

    function fakeTemplate() 
    {
        return { 
            then: function(modal){
                $scope.modal_login = modal;
            }
        }
    }

    beforeEach(inject(function(_$controller_, _$rootScope_)
    {
        $controller = _$controller_;
        $rootScope = _$rootScope_;
        $scope = _$rootScope_.$new();

        $ionicModal = 
        {
            fromTemplateUrl: jasmine.createSpy('$ionicModal.fromTemplateUrl').and.callFake(fakeTemplate)
        }; 

        var controller = $controller('MainCtrl', { $scope: $scope, $rootScope: $rootScope, $ionicModal: $ionicModal });
    }));


    describe('Modal tests', function() 
    {
        beforeEach(function()
        {
            $scope.open_login_modal();
            spyOn($scope.modal_login, 'show'); // NOT WORKING
            spyOn($scope.modal_login, 'hide'); // NOT WORKING
        });

        it('should open login modal', function() 
        {
            expect($ionicModal.fromTemplateUrl).toHaveBeenCalled(); // OK
            expect($ionicModal.fromTemplateUrl.calls.count()).toBe(1); // OK
            expect($scope.modal_login.show()).toHaveBeenCalled(); // NOT PASS
            expect($scope.for_test_only).toEqual(true); // NOT PASS
        });

        it('should close login modal', function() 
        {
            $scope.close_login_modal();     
            expect($scope.modal_login.hide()).toHaveBeenCalled(); // NOT PASS
        });
    });

});

从代码 $scope.for_test_only 可以看出,它应该等于 true,但无法识别。我收到此错误消息:

Expected undefined to equal true.

show() 和 hide() 方法也是如此。测试中看不到它们。

我认为是因为它们没有在间谍中声明。

问题:

我怎样才能正确地监视模式?

非常感谢!

【问题讨论】:

    标签: javascript angularjs ionic-framework jasmine karma-runner


    【解决方案1】:

    这里的问题可以推断为如何正确地监视一个承诺。您在这里非常正确。

    但是,如果你想测试调用成功的回调函数,你必须执行两个步骤:

    1. 模拟服务(在您的情况下为 $ionicModal)并返回一些假函数
    2. 在该假函数中,执行生产代码传递给您的回调。

    这是一个插图:

    //create a mock of the service (step 1)
    var $ionicModal = jasmine.createSpyObj('$ionicModal', ['fromTemplateUrl']);
    
    //create an example response which just calls your callback (step2)
    var successCallback = {
       then: function(callback){
           callback.apply(arguments);
       }
    };
    
    $ionicModal.fromTemplateUrl.and.returnValue(successCallback);
    

    当然,如果您不想自己维护承诺,您可以随时使用 $q:

    //in your beforeeach
    var $ionicModal = jasmine.createSpyObj('$ionicModal', ['fromTemplateUrl']);
    //create a mock of the modal you gonna pass and resolve at your fake resolve
    var modalMock = jasmine.createSpyObj('modal', ['show', 'hide']);
    $ionicModal.fromTemplateUrl.and.callFake(function(){
        return $q.when(modalMock);
    });
    
    
    //in your test
    //call scope $digest to trigger the angular digest/apply lifecycle
    $scope.$digest();
    //expect stuff to happen
    expect(modalMock.show).toHaveBeenCalled();
    

    【讨论】:

    • 天哪!谢谢!已经把头撞到墙上了这么长时间!我已经准备好为你建造一座雕像@baba!给出一般规则的回复也很好。同样有趣的是 $scope.$digest();对于使一切正常工作至关重要。我会更多地研究为什么会这样。
    • 哈哈,没问题,我不得不说我也花了一些艰苦的时间试图弄清楚这一点,但我总是很乐意提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-05-06
    • 2021-11-30
    • 2015-09-14
    • 2014-06-24
    • 1970-01-01
    • 2013-01-09
    • 2016-01-13
    相关资源
    最近更新 更多