29

テスト仕様ファイルは次のとおりです。

describe('Test main controller', function(){
        it('Should initialize value to Loading', function(){
            $scope = {}
            ctrl =  new mainNavController($scope)
            expect($scope.wksp_name).toBe('Loading')
        })
    })

ここにコントローラーファイルがあります

function mainNavController($scope) {
    $scope.wksp_name = 'Loading...'
    $scope.$on('broadCastWkspNameEvent', function (e, args) {
        $scope.wksp_name = args
    })
}

mainNavController.$inject=['$scope']

しかし、私のテストは言って失敗しますObject #<Object> has no method '$on'

ジャスミンの基本設定を使用しています。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Jasmine Spec Runner</title>

  <link rel="shortcut icon" type="image/png" href="testlib/jasmine-1.2.0/jasmine_favicon.png">
  <link rel="stylesheet" type="text/css" href="testlib/jasmine-1.2.0/jasmine.css">
  <script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine.js"></script>
  <script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine-html.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="/static_files/js/test-specs/main-nav-spec.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="/static_files/js/common/jquery/latest.js"></script>
  <script type="text/javascript" src="/static_files/js/common/angular/angular-1.0.1.min.js"></script>
  <script type="text/javascript" src="/static_files/js/common/angular/angular-resource-1.0.1.min.js"></script>
  <script type="text/javascript" src="/static_files/js/section/main-nav-controller.js"></script>

  <script type="text/javascript">
    (function() {
      var jasmineEnv = jasmine.getEnv();
      jasmineEnv.updateInterval = 1000;

      var htmlReporter = new jasmine.HtmlReporter();

      jasmineEnv.addReporter(htmlReporter);

      jasmineEnv.specFilter = function(spec) {
        return htmlReporter.specFilter(spec);
      };

      var currentWindowOnload = window.onload;

      window.onload = function() {
        if (currentWindowOnload) {
          currentWindowOnload();
        }
        execJasmine();
      };

      function execJasmine() {
        jasmineEnv.execute();
      }

    })();
  </script>

</head>

<body>
</body>
</html>

私が間違っているのは何ですか?このことがどのように機能するのか理解できません:)

4

3 に答える 3

59

テストコードの主な問題は、new演算子を使用して「手動で」コントローラーのインスタンスを作成しようとすることです。そうするとき、AngularJSは依存性を注入する機会がありません。あなたがすべきことは、AngularJSが依存性を注入できるようにすることです:

var $scope, ctrl;

//you need to inject dependencies first
beforeEach(inject(function($rootScope) {
    $scope = $rootScope.$new();        
}));

it('Should initialize value to Loading', inject(function($controller) {
    ctrl = $controller('MainNavController', {
        $scope: $scope
    });
    expect($scope.wksp_name).toBe('Loading...');
}));

完全なjsFiddleへのリンクは次のとおりです。http://jsfiddle.net/pkozlowski_opensource/7a7KR/3/

上記の例では、注目に値する2つのことがあります。

  1. ngMockモジュールのinject()メソッドを使用して、依存性を注入できます:https ://docs.angularjs.org/api/ngMock/function/angular.mock.inject
  2. (依存性注入をサポートする)コントローラーインスタンスを作成するには、$ controllerサービスを使用します:http://docs.angularjs.org/api/ng.$controller

最後のコメントとして、私はコントローラーに大文字で始めることをお勧めします-このようにして、コントローラーを変数名と混同しないようにします。

于 2012-09-04T17:20:26.197 に答える
17

@pkozlowski.opensource による優れた回答。$scope.$onもう少し詳しく説明すると...コントローラーによって実際に呼び出されたと主張することも便利な場合があります。この場合、$scope.$on以下に示すようにスパイできます。

beforeEach(inject(function($rootScope) {
    $scope = $rootScope.$new();        
    spyOn($scope, '$on').andCallThrough();
}));

そして$on、イベント名といくつかの関数を引数として呼び出されたことをアサートできます。

it('Should bind to "broadCastWkspNameEvent"', inject(function($controller) {
    ctrl = $controller('MainNavController', {
        $scope: $scope
    });
    expect($scope.$on).toHaveBeenCalledWith('broadCastWkspNameEvent', jasmine.any(Function));
}));
于 2013-02-01T08:06:08.790 に答える
4

pkozowski の回答には同意しますが、質問に直接答えるには、「$on」をスタブ化する必要があります

$scope が次のようになっている場合、例は合格します。

$scope = {
  $on: function() {}
}
于 2012-09-29T13:07:51.733 に答える