如何在jasmine测试中为有角度的项目注入依赖项

How to inject dependencies in jasmine test for an angular item

本文关键字:项目 注入 依赖 jasmine 测试      更新时间:2023-09-26

这是测试规范文件:

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>

我做错了什么?我不明白这个东西应该如何工作:)

测试代码的主要问题是它试图使用新运算符"手动"创建控制器的实例。当这样做时,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/

在上面的例子中有两件事值得注意:

  1. 您可以使用ngMock模块中的inject()方法来注入依赖项:https://docs.angularjs.org/api/ngMock/function/angular.mock.inject
  2. 要创建控制器实例(支持依赖项注入),您可以使用$controller服务:http://docs.angularjs.org/api/ng.$控制器

最后一句话:我建议以大写字母开头命名控制器,这样我们就不会将它们与变量名混淆。

@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));
}));

我同意pkozowski的回答,但要更直接地回答您的问题,您需要在上去掉'$'

如果你的$scope看起来像:,你的例子就会通过

$scope = {
  $on: function() {}
}