在 Karma 中测试 angular 控制器

Testing angular controller in Karma

我和我的团队在 Jasmine 上使用 Karma 测试运行程序设置控制器测试时遇到问题。

app/app.js

buyItApp = angular.module('buyItApp', ['ionic']);

app/controllers/userSearchCtrl.js

buyItApp.controller("userSearchCtrl", function($http, $scope) {
  var self = this;
  self.searchQuery = function(searchData) {
    $( "ion-spinner").toggle(true);
    $http({
      method: 'GET',
      url: 'http://productfeedtest.wandoso.com/?keyword=' + searchData
    }).then(function successCallback(response) {
      $( "ion-spinner").toggle(false);
      $scope.showResultsCount = true
      $scope.items = response.data.items;
      $scope.isOffer = response.data.is_special_offer;
      $scope.resultsCount = response.data.items.length;
      $scope.searchQuery = searchData;
    }, function errorCallback(response) {
      $scope.searchResults = "server error!"
    });
  }
});

test/karma.conf.js

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular.min.js',
      'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-mocks.js',
      'https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-scenario.js',
      '../public/javascripts/app/*.js',
      '../public/javascripts/app/controllers/*.js',
      'unit/userSearchCtrl.spec.js',
      'unit/*.spec.js'
    ],

    exclude: [
    ],

    preprocessors: {
    },

    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS'],
    singleRun: false,
    concurrency: Infinity
  })
}

test/unit/userSearchCtrl.spec.js

describe('userSearchCtrl', function() {

    var $rootScope, $scope, $controller, userSearchCtrl;

    beforeEach(module('buyItApp'));

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

        userSearchCtrl = $controller('userSearchCtrl', {'$rootScope' : $rootScope, '$scope': $scope});
    }));

    it('should exist', function() {
        expect(userSearchCtrl).toBeDefined();
    });
});

The failing test result

http://textuploader.com/5jo6b

最值得注意的是:

Expected undefined to be defined.
        at /Users/Harry/Dropbox/Dev/buyIt/test/unit/userSearchCtrl.spec.js:16
PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.004 secs / 0.007 secs)

看起来 Karma 找不到控制器,但是在检查代码和查看其他项目后,问题是什么不太清楚。

我认为问题在于您不使用模拟。

beforeEach(module('buyItApp')); 是 afaik 实例化一个真实的模块。这显然失败了,因为您没有包含依赖项。

另外,如果你想模拟控制器的功能,你应该使用 angular.mock.inject 而不是 inject.

这个我不太清楚,但我一直都是这样做的。

那么您的规格将如下所示:

describe('userSearchCtrl', function() {
    var $rootScope, $scope, $controller, userSearchCtrl;

    beforeEach(angular.mock.module('buyItApp'));

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

        userSearchCtrl = $controller(
            'userSearchCtrl', 
            {
                '$rootScope' : $rootScope, 
                '$scope': $scope
            }
        );
   }));

   it('should exist', function() {
       expect(userSearchCtrl).toBeDefined();
    });
});

作为错误

> http://errors.angularjs.org/1.5.0-beta.1/$injector/modulerr?p0=buyItApp&p1=Error:
> [$injector:modulerr]
> http://errors.angularjs.org/1.5.0-beta.1/$injector/modulerr?p0=ionic&p1=Error:
> [$injector:nomod]
> http://errors.angularjs.org/1.5.0-beta.1/$injector/nomod?p0=ionic

明确表示,它无法找到 buyItApp 中加载的 ionic 模块。因为它没有包含在 Karma files.