10

ネストされたコントローラーの単体テストを作成しようとしていますが、テストで同じ動作をモックする方法がわかりません。

私は2つのコントローラーを持っています:

function FirstController ($scope) {
    $scope.childs = [{
         title : 'Hello, earth!'
    }];
};

function SecondController ($scope) {
    $scope.child.title = $scope.child.title + $scope.$index;
};

そして私のHTMLでは:

<div data-ng-controller="FirstController">
    <div data-ng-repeat="child in childs" data-ng-controller="SecondController">
        {{ child.title }}
    </div>
</div>

そして、これは期待どおりに機能します(http://jsfiddle.net/tcayp/1/

ユニットテスト:

// FirstController
it('Should have childs', function () {
    scope = {};
    ctrl = new FirstController(scope);
    expect(scope.childs.length).toBeGreaterThan(0);
});
// SecondController
it('Should have inherited a child', function () {
    scope = {};
    ctrl = new SecondController(scope);
    expect(scope.child.title).toEqual('Hello, earth!0');
});

SecondController-testでは、ng-repeatから継承チェーンをモックする方法がわかりません。

4

3 に答える 3

16

理想的には、単体テストでは、クラス(ユニット)を個別にテストしたいと思います。1回のテストで2つのコントローラーをテストするのは多すぎる可能性があります。テストはより複雑になり、より脆弱になります。

提供されている例を詳しく見ると、実際には2つのコントローラーをテストするのではなく、親スコープでデータが使用可能であることを確認する必要があることに気付くかもしれません。SecondControllerしたがって、1つのコントローラーのみ( )と継承されたデータに焦点を当てると、次のようなテストが作成されます。

describe('Testing the SecondController controller', function() {

    var $parentScope, $scope, ctrl;
    it('should prepare title', inject(function($rootScope, $controller) {

        //setup hierarchy of scopes with data             
        $rootScope.childs = [{
            title : 'Hello, earth!'
        }];
        $scope = $rootScope.$new();
        $scope.$index = 1;

        ctrl = $controller('SecondController', {
            $scope: $scope
        });

        expect($scope.childs[0].title).toEqual('Hello, earth!1');        
    }));
});

これが完全なjsFiddleです:http://jsfiddle.net/pkozlowski_opensource/h8xry/13/

2つのコントローラーを一緒にテストすることはお勧めしませんが、質問に答えるために、次のことも可能です。

describe('Testing the SecondController controller', function() {

    it('should prepare title', inject(function($rootScope, $controller) {

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

        var $scope = $rootScope.$new();
        $scope.$index = 1;

        ctrl = $controller('SecondController', {
            $scope: $scope
        });

        expect($scope.childs[0].title).toEqual('Hello, earth!1');        
    }));
});

そしてjsFiddle: http: //jsfiddle.net/pkozlowski_opensource/4Qy6b/1/

于 2012-09-18T10:38:08.413 に答える
2

AngularJSのドキュメントでは、ネストされたコントローラーをそれぞれインスタンス化し、アプリと同じスコープ階層を確立することで、ネストされたコントローラーをテストすることを提案しています。これは、(ある程度まで)現実的なコンテキストでコントローラーをテストする必要があるため、理にかなっています。

于 2015-01-22T22:53:23.870 に答える
1

テストでは、新しいスコープで親コントローラーをインスタンス化します。

mainScope = $rootScope.$new();
$controller('ParentController', {$scope: mainScope});

子コントローラーで、以前にインスタンス化されたスコープを使用して新しいスコープをインスタンス化します。

childScope = mainScope.$new();
$controller('ChildController', {$scope: childScope});

AngularJSドキュメントの例:

describe('state', function() {

  var mainScope, childScope, grandChildScope;

  beforeEach(module('myApp'));

  beforeEach(inject(function($rootScope, $controller) {
      mainScope = $rootScope.$new();
      $controller('MainController', {$scope: mainScope});
      childScope = mainScope.$new();
      $controller('ChildController', {$scope: childScope});
      grandChildScope = childScope.$new();
      $controller('GrandChildController', {$scope: grandChildScope});
  }));

  it('should have over and selected', function() {
      expect(mainScope.timeOfDay).toBe('morning');
      expect(mainScope.name).toBe('Nikki');
      expect(childScope.timeOfDay).toBe('morning');
      expect(childScope.name).toBe('Mattie');
      expect(grandChildScope.timeOfDay).toBe('evening');
      expect(grandChildScope.name).toBe('Gingerbread Baby');
    });
});
于 2016-06-29T17:13:07.553 に答える