Angular/Ionic项目的单元测试

5
我有一个非常简单的控制器,看起来像这样。
timeInOut.controller('timeInOutController', function($scope, $filter, $ionicScrollDelegate){

    ... 

});

每当我尝试创建一个单元测试,就像这样...
(function() {
'use strict';

    var scope, controller, filter;

    describe('timeInOutController', function () {

        beforeEach(module('common.directives.kmDateToday'));

        beforeEach(inject(function ($rootScope, $controller, $filter) {
            scope = $rootScope.$new();
            filter = $filter;
            controller = $controller('timeInOutController', {
                $scope: scope
            });
        }));

        describe('#date setting', function(){

            ...

        });
    });
})();

我遇到了错误:
[$injector:unpr] Unknown provider: $ionicScrollDelegateProvider <- $ionicScrollDelegate 显然,在我的示例中,我并没有试图将$ionicScrollDelegate注入到测试中,这只是因为我已经尝试了许多种方式,但都没有成功,并且不知道哪种尝试失败了。
此外,在我的karma.conf.js文件中,我包含了ionic.bundle.js和angular-mocks.js库/文件。
我可以成功地对任何不使用$ionic的内容进行单元测试,因此我知道我的测试框架已正确设置,问题在于注入任何与$ionic有关的内容。
2个回答

6
如果你要通过angular实例化你的控制器,需要传入所有参数。通过添加这些参数,你告诉angular,每当你创建这些控制器时,我需要这些东西,因为我依赖于它们。
所以我的建议是模拟这些依赖关系的某些表示,并在创建控制器时注入它们。它们不必(也不应该)是你单元测试中的实际服务。Jasmine让你能够创建间谍对象,你可以注入它们,以验证该单元的行为。
(function() {
'use strict';

    var scope, controller, filter, ionicScrollDelegate;

    describe('timeInOutController', function () {

        beforeEach(module('common.directives.kmDateToday'));

        beforeEach(inject(function ($rootScope, $controller, $filter) {
            scope = $rootScope.$new();
            filter = $filter;

            // func1 and func2 are functions that will be created as spies on ionicScrollDelegate
            ionicScrollDelegate = jasmine.createSpyObj('ionicScrollDelegate', ['func1', 'func2']
            controller = $controller('timeInOutController', {
                $scope: scope,
                $filter: filter,
                $ionicScrollDelegate: ionicScrollDelegate
            });
        }));

        describe('#date setting', function(){

            ...

        });
    });
})();

你可以通过Jasmine的文档了解更多关于间谍的内容。

我有点理解你的意思,但你能否给一个快速的代码示例呢?你是指像一个单独的文件夹/文件,模拟一些ionic依赖项并注入它们吗? - Hoser
这个可行,唯一需要改变的是将 createSpyObject(...) 改为 createSpy(...,不确定 createSpyObject 是否是一个实际的函数。非常感谢! - Hoser
1
我在没有查看文档的情况下添加了这个,但我所指的方法是createSpyObj,它有助于在对象上创建多个spy。 - Brocco
好的信息。再次感谢你! - Hoser

3
你需要为控制器使用的所有依赖项创建模拟对象。
以这个控制器为例:
angular.module('app.module', [])
    .controller('Ctrl', function($scope, $ionicLoading) {
        $ionicLoading.show();
    });

在这里你正在使用 $ionicLoading 服务,所以如果你想测试这个控制器,你需要模拟该对象,并且指定你在控制器中使用的方法

describe('Test', function() {
     // Mocks
     var $scope, ionicLoadingMock;
     var ctrl;
     beforeEach(module('app.module'));
     beforeEach(function() {
         // Create $ionicLoading mock with `show` method
         ionicLoadingMock = jasmine.createSpyObj('ionicLoading', ['show']);
         inject(function($rootScope, $controller) {
             $scope = $rootScope.$new();
             ctrl = $controller('Ctrl', {
                 $scope: $scope,
                 $ionicLoading: ionicLoadingMock
             });
         });
     });
     // Your test goes here
     it('should init controller for testing', function() {
         expect(true).toBe(true);
     });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接