19

解決プロパティを使用してコントローラーをテストするにはどうすればよいですか? エラーがスローされます:不明なプロバイダー: InitProvider、テスト中、当然のことです。どうすればテストできますか?

ルート構成で init プロパティを使用してデータをロードし、コントローラーのインスタンス化時にコントローラーに渡すことで、データがロードされる前にルートが変更されないようにします。

  $routeProvider
    .when('/topic/:topic_id/content/:content_id', {
      templateUrl: 'views/content.html',
      controller: 'ContentCtrl',
    resolve: {
      init: ContentCtrl.init
    }
    });

そもそもパターンが完全に間違っているのでしょうか?

'use strict';

var ContentCtrl = ['$scope', '$location', '$routeParams', 'init', function ($scope, $location, $routeParams, init) {

    $scope.contents = init.contents;

  }];

ContentCtrl.init = ['$q', 'app_config', '$log', '$timeout', function ($q, app_config, $log, $timeout) {

    var defer = $q.defer();

    $log.log("ContentCtrl loading..");

    $timeout(function() {
        defer.resolve({contents: [
                                    {message: 'Hello!'}
                                  ]});

        $log.log("ContentCtrl loaded.");

    }, 2000);

    return defer.promise;
}];

angular.module('studentportalenApp').controller('ContentCtrl', ContentCtrl);

コントローラー全体を 内にカプセル化したい.controler('ContentCtrl', function() { ... })のですが、ルート構成で init を使用できるようにするためにこれを正しく行う方法をまだ理解していません。

4

4 に答える 4

26

ここで同じことに遭遇しました。https://groups.google.com/forum/?fromgroups=#!topic/angular/LzXm-9nwkjYのアプローチを使用して解決しました。

基本的には、単純な変数を使用して通常送信されるデータをモックし、テストでコントローラーに追加しました。あなたの場合、私はそれが次のように見えると思います:

var initData = {
      contents: [{message: 'Hello!'}]
};
$controller("ContentCtrl", { $scope: ..., init: initData });
于 2013-03-22T10:32:16.280 に答える
9

charlietfl が提案したように、最終的にはすべてをサービスに変換することで解決されました。

例:

ルート構成:

//This helper injects a function with the service 
//defined in the initMethod string and returns services.prepare()
var interceptWith = function(initMethod) {
        return [initMethod, function(m) {
                    return m.prepare();
                }];
}

$routeProvider        
    .when('/foobar/', {
        templateUrl: 'foobar.html',
        controller: 'FoobarCtrl',
        resolve: {
            init: interceptWith('FoobarCtrlInit')
        }
    });

foob​​ar コントローラーの定義:

angular.module('fooApp').controller('FoobarCtrl', ['$scope', 'init', function ($scope, init) {              
            $scope.data = init.data;    
  }])
.service('FoobarCtrlInit', ['$q', '$timeout', function ($q, $timeout) {

        var _prepare = function() {

            var deferred = $q.defer();

            //Fake async loading of data
            $timeout(function() {
                 deferred.resolve({data: ['A','B','C']});
            }, 1000);




            return deferred.promise; 
        }

        return {
            prepare: _prepare
        }
}]);

これをテストするには、次のようにします。

'use strict';

describe('Controller: FoobarCtrl', function() {

  // load the controller's module
  beforeEach(module('fooApp'));

  var FoobarCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function($controller) {
    scope = {};
    CourseCtrl = $controller('FoobarCtrl', {
      $scope: scope,
      init: {data: ['Testdata A', 'B', 'C']}
    });
  }));

  it('should attach a list of data to the scope', function() {
    expect(scope.data.length).toBe(3);
  });
});
于 2013-03-24T15:41:06.627 に答える
1

$routeProvider で解決を使用すると、カルマで同じエラーが発生しました。次のように、app.js の単体テストで解決をテストして修正しました。

describe("myApp",  function() {

  beforeEach(module('myApp'));

  it('should resolve initial values for my Controller', inject(function( $route ) {
    expect($route.routes['/'].resolve.init).toBeDefined; //or whatever test you want
  }));
});

そして、コントローラーの説明内で次のように、コントローラーのテストで値をモックしました。

//mock out the resolved values to isolate controller code
  beforeEach(module(function($provide) {
    $provide.value('init', function() {
      return 'whatever data you need to mock';
    });
于 2015-08-20T01:55:22.773 に答える
0

ルートの解決された値を単体テストするには:

var resolveObject = $injector.invoke($route.current.$$route.resolve.testedObject);

于 2016-02-10T08:44:41.900 に答える