【问题标题】:Angular Karma Unit Testing Controller Not Injecting Mocked Service DependencyAngular Karma 单元测试控制器不注入模拟服务依赖项
【发布时间】:2015-06-16 15:49:47
【问题描述】:

我尝试了各种方法来实例化模拟服务“listFilterManager”并将其传递给控制器​​。尽管已创建并可以访问模拟服务,但当执行 scope.$digest() 时,实际的非模拟服务会运行而不是模拟的 listFilterManager。更令人困惑的是,resourceStore 服务被正确地模拟和注入。任何帮助将不胜感激。

相关代码:

    beforeEach(function(){
        module('listModule');
        module(function($provide){
            $provide.factory('resourceStore', function(){
                return {
                    alertsArray: Object.keys(mockData).map(function(key){
                        return mockData[key];
                    })
                };
            });
            $provide.value('listFilterManager',{
                filterList: jasmine.createSpy('filterList').and.callFake(function(input){
                    return input;
                })
            });
        });
    });

    describe('instantiates the Alert List Ctrl', function(){
        var scope, listFilterParams, listFilterManager, resourceStore, tableAccessorDictionaries, AlertListCtrl;
        beforeEach(function(){
            inject(function(_$rootScope_, $controller, _tableAccessorDictionaries_, _listFilterParams_, _resourceStore_, _listFilterManager_){
                scope = _$rootScope_.$new();
                listFilterParams = _listFilterParams_;
                listFilterManager = _listFilterManager_; //this refs the mocked service, but the actual service is the one that is executed.
                var deps = {
                    '$scope': scope,
                    'tableAccessorDictionaries': _tableAccessorDictionaries_,
                    'listFilterManager': _listFilterManager_,
                    'listFilterParams': _listFilterParams_,
                    'resourceStore': _resourceStore_
                };
                AlertListCtrl = $controller('AlertListCtrl', deps);
            });
        });

        it('it should filter the list when a list filter parameter changes', function(){
            expect(listFilterManager.filterList).not.toHaveBeenCalled();
            scope.filterParams.text = 'This is a test query';
            scope.$digest();
            expect(listFilterManager.filterList).toHaveBeenCalled();
        });

    });

【问题讨论】:

    标签: angularjs unit-testing dependency-injection karma-jasmine


    【解决方案1】:

    所以您说“listFilterManager”是一项服务,但在 beforeEach 方法中,您将它作为一个值提供。您需要将其作为工厂提供,以便正确模拟它。替换如下

                   $provide.value('listFilterManager',{
                filterList: jasmine.createSpy('filterList').and.callFake(function(input){
                    return input;
                })
            });
    

    与:

                   $provide.factory('listFilterManager', function () {
                     return {
                       filterList: jasmine.createSpy('filterList').and.callFake(function(input){
                         return input;
                     };
                   })
            });
    

    它应该可以正常工作。

    【讨论】:

    • 不幸的是,当我说我尝试了“各种方法”时,那是其中之一。我只是再次将其插入以查看但没有骰子,它仍然调用真正的服务而不是模拟的服务。感谢您的意见!
    • (可选)您是否尝试过删除listFilterManager = _listFilterManager_; 行?可以肯定的是,一旦您 $provide 服务,您就不必将其直接注入控制器。例如,如果你已经模拟了控制器的所有依赖项并 $provided 它们,你可以使用myController = $controller('myController', {}) 初始化控制器
    • 运气不好。变量 listFilterManager 确实引用了模拟服务,仅供参考,问题只是控制器本身似乎总是使用真实的服务。我刚刚尝试了你的模拟一切然后不显式注入的建议,但结果是一样的。
    【解决方案2】:

    一段时间后,我想通了。问题是因为我正在测试的函数是从 underscore.debounce 包装器中调用的。 Debounce 显然会导致测试问题,如 here 所述。解决方案是在测试文件中重新定义 _.debounce (归功于上述帖子):

    _.debounce = function (func) { return function () { func.apply(this, arguments);}; };
    

    哇,多么令人沮丧的问题,但希望这会帮助其他有需要的人!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      相关资源
      最近更新 更多