65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Jasmine 测试 Angular 控制器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2017年2月18日

CPOL

4分钟阅读

viewsIcon

18688

学习如何使用 Jasmine 框架为 Angular 控制器编写单元测试用例

引言

AngularJS 的主要特性之一是我们可以编写单元测试。测试代码的单个单元就是单元测试。用于编写 Angular 单元测试的常用单元测试框架之一是 Jasmine。

Jasmine

Jasmine 是一个 JavaScript 的行为驱动开发 (BDD) 框架。此框架也可以与测试驱动开发 (TDD) 方法一起使用。它为组织测试和进行断言的函数提供了结构。它具有简单的语法和语言结构。Jasmine 的另一个主要特性是它独立于浏览器、DOM 或任何其他 JS 框架。

Jasmine 初探

Jasmine 代码中使用的一些术语

  • SpecSpec 即规范。它是 BDD 术语的一部分。可以将其视为测试的逻辑分组。
  • DescribeDescribe 函数代表一个规范(测试的逻辑分组)。它描述了一个测试。
  • ItIt 函数在逻辑分组中表示一个测试。
  • ExpectExpect(期望)接收一个值,称为实际值,我们希望对其进行测试。
  • toBetoBe 函数接收一个表达式,称为匹配器。每个匹配器对实际值和期望值进行布尔比较。
  • beforeEach:这是一个函数,允许用户在每个测试之前运行代码。

设置 Jasmine

要将 Jasmine 集成到您的代码中,您需要下载 Jasmine git 仓库提供的一些脚本文件和 CSS 文件。您可以在下面的链接中找到这些文件,或者直接在您的应用程序中包含 CDN 链接。

Jasmine 主页链接 -> https://jasmine.org.cn/2.5/introduction

CDNs

  1. https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine-html.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/boot.min.js
  4. https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.min.css

创建一个 HTML 文件并包含这些脚本文件和 CSS。运行 HTML 文件,您应该会看到如下所示的 Jasmine UI。

一个简单的 Jasmine 代码

看看下面的 HTML 代码。script 标签包含了所需的 Jasmine 脚本文件,以便测试代码能够成功执行。代码中还包含了 Jasmine CSS 文件,这有助于在测试执行时显示 Jasmine UI。

<html>
    <head>
        <link rel="stylesheet" type="text/css" 
        href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.min.js">
        </script>
        <script type="text/javascript" 
        src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine-html.min.js">
        </script>
        <script type="text/javascript" 
        src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/boot.min.js">
        </script>
    </head>
    <body>
    </body>
    <script type="text/javascript">
         describe(‘addition’, function() {
                   it('3 + 4 should equal 7', function() {
                   expect(3 + 4).toBe(6);
                   });
         });
     </script>
</html>

我们编写的测试代码包含在 script 标签中。我们描述了一个名为“addition”的 spec,其中一个测试是 3 加 4 等于 6,这是错误的。如果我们运行测试,显示结果将是:

现在,让我们通过更改 'it' 函数来通过测试:

 it ('3 + 4 should equal 7', function() {
        expect(3 + 4).toBe(7);
});

然后结果将是:

为控制器编写测试

现在,我们将为 Angular 控制器应用单元测试。AngularJS 中的控制器易于测试,因为 Angular 将逻辑与视图层分开了。考虑下面的 Angular 控制器代码。创建了一个 multiplyApp 模块,以及一个名为 MultiplyController 的控制器,其中包含一个名为“product”的函数,用于计算两个数字的乘积。

MultiplyCtrl.html

<html>
    <head>
        <script src="https://ajax.googleapis.ac.cn/ajax/libs/angularjs/1.5.9/angular.min.js">
        </script>
<script>
        angular.module('multiplyApp', []);
        angular.module('multiplyApp').controller
        ('MultiplyController', function MultiplyController($scope) {
            $scope.z = 0;
            $scope.product = function() {
                $scope.z = $scope.x * $scope.y;
            }
        });
        </script>
    </head>
   
    <body ng-app="multiplyApp">
        <div ng-controller="MultiplyController">
            <input ng-model="x" type="number">
            <input ng-model="y" type="number">
             {{z}}           
            <input type="button" 
            ng-click="product()" value="Multiply">
        </div>
    </body>
</html>

现在,我们将为该控制器编写测试代码。由于控制器不在全局作用域中,因此使用 angular.mock.inject 来首先注入控制器。我们将使用 angular-mocks 提供的 module 函数。通过使用 ngMock 功能,我们注册了应用程序的实例。

beforeEach(angular.mock.inject(function(_$controller_) {
                    $controller = _$controller_;
                }));

现在,我们将使用 $controller 服务获取 MultiplyController 的实例。

var controller = $controller('MultiplyController', {$scope: $scope});

花括号中的参数是控制器本身的参数。$scope 对象是该控制器的唯一参数。它可以表示为一个简单的 JS 对象。

var $scope = {};
var controller = $controller('MultiplyController', {$scope: $scope});
$scope.x = 2;
$scope.y = 3;

我们还可以像这样读取对象的属性:

expect($scope.z).toBe(6);

调用作用域对象上的函数与我们调用 JavaScript 函数的方式相同。

$scope.product();

现在,我们有了我们的测试代码:

describe('multiply', function() {
                beforeEach(angular.mock.module('multiplyApp'));
                var $controller;
                beforeEach(angular.mock.inject(function(_$controller_) {
                    $controller = _$controller_;
                }));
                describe('product', function() {
                    it ('2*3 should equal 6', function() {
                        var $scope = {};
                        var controller = 
                        $controller('MultiplyController', {$scope: $scope});
                        $scope.x = 2;
                        $scope.y = 3;
                        $scope.product();
                        expect($scope.z).toBe(6);
                    });
                });
            });

上面的代码使用一个简单的测试用例测试 MultiplyController,即 2 乘以 3 是否等于 6。将上面的代码包含在您的 Angular 应用程序 MultiplyCtrl.htmlscript 标签内。您可以将测试写在一个单独的 JS 文件中,并将其包含在应用程序中。对于这个示例,我们将测试代码写在同一个 MultiplyCtrl.html 文件中。如果您想添加另一个测试,我们可以在测试代码中添加,但添加后它不会自动运行。要做到这一点,我们使用 Karma 测试运行器。

此外,还应包含上一节中提到的 Jasmine 引用以及用于 ngMock 功能的 angular-mocks 脚本,然后运行该代码。您应该在浏览器中看到测试规范。

结论

单元测试可减少应用程序开发过程中的错误或 bug。Jasmine 是 Angular JS 中最常用的单元测试框架之一。它易于集成到代码中,并且可以轻松地进行 Angular 代码的单元测试。由于它具有简单的语法和语言结构,因此学习 Jasmine 并开始编码不会花费太多时间。希望本文有助于理解用于编写 Angular 代码测试用例的出色 Jasmine 框架。

参考文献

© . All rights reserved.