JasmineJS - 快速指南

JasmineJS - 概述

Jasmine 是一个开源 JavaScript 框架,能够测试任何类型的 JavaScript 应用程序。Jasmine 遵循行为驱动开发 (BDD) 程序,以确保每行 JavaScript 语句都经过适当的单元测试。通过遵循 BDD 程序,Jasmine 提供了一种小语法来测试整个应用程序的最小单元,而不是将其作为一个整体进行测试。

为什么使用 Jasmine?

与其他可用的 JavaScript 测试框架相比,使用 Jasmine 的优势如下 −

  • Jasmine 不依赖于任何其他 JavaScript 框架。

  • Jasmine 不需要任何 DOM。

  • Jasmine 框架中使用的所有语法都清晰明了。

  • Jasmine 深受 Rspec、JS Spec 和 Jspec 的影响。

  • Jasmine 是一个开源框架,可以轻松获得不同版本,如独立版本、ruby gem、Node.js 等。

如何使用Jasmine?

Jasmine 非常容易在任何开发方法中实现。您只需从官方网站 https://jasmine.github.io/ 下载独立库文件,然后在您的应用程序中实现它即可。

详细的环境设置将在下一章"环境设置"中描述。成功下载并解压 zip 文件后,您将在该 zip 文件中找到以下子文件夹。

Zip File

JasmineJS - 环境设置

在本章中,我们将讨论如何设置基于 Jasmine 的 BDD 测试应用程序的分步过程。

步骤 1 − 转到 jasmine 的官方网站 https://jasmine.github.io/

Official Site

步骤 2 − 单击任意版本链接。最好使用最新版本"Edge"。您将被重定向到所选版本的主页。

主页

步骤 3 − 转到主页的下载部分,然后单击独立发布页面。

下载部分

步骤 4 − 重定向到 github 发布页面后,从那里下载 Zip 文件。

发布页面

步骤 5 − 解压下载的 jasmine-standalone-2.4.1 文件夹。您将看到以下文件夹结构。

Standalone

步骤 6 − 现在在您最喜欢的 IDE 中创建一个 Web 应用程序项目,并将下载的库文件添加到应用程序中。这里,我们使用了 netbeans IDE。以下是添加 Jasmine 框架后我们的应用程序的目录结构。

Project

我们的环境设置已完成。现在我们的应用程序已准备好通过 Jasmine 框架进行测试。

JasmineJS - 编写文本和执行

在本章中,我们将创建一个 hello world 应用程序,它将测试我们的 "helloworld.js" 文件。在开发 hello world 应用程序之前,请返回上一章并确保您的环境已准备好使用 Jasmine 进行测试。

步骤 1 − 在您的 IDE 中创建一个 Web 应用程序

在这里我们使用 NetBeans 8.1 在 Jasmine 中开发我们的 hello world 应用程序。在 NetBeans 中,转到文件 → 新建项目 → Html5/JS 应用程序并创建一个项目。创建项目后,项目目录应如以下屏幕截图所示。我们将项目命名为 Jasmine_Demo

Demo

第 2 步 − 将 Jasmine lib 文件包含到应用程序中

创建演示项目后,您需要做的就是将 Jasmine 库的解压文件夹包含在所创建应用程序的 Unit Tests 文件夹中。将所有库文件添加到我们的应用程序文件夹后,我们的项目结构将如以下屏幕截图所示。

项目结构

specsrc 文件夹下给出的文件是 Jasmine 团队提供的演示文件。删除这些文件,因为我们将创建自己的测试文件和测试用例。在删除这些 JavaScript 文件时,我们需要删除输出 html 文件 SpecRunner.html 中对这些文件的引用。

以下是 SpecRunner.html 文件的屏幕截图,其中将删除 specsrc 中不同 JavaScript 文件的引用。

SpecRunner Html File

步骤 3 − 创建 JavaScript 文件

在此步骤中,我们将在 src 文件夹下创建一个名为 helloworld.js 的 JavaScript 文件。这是我们将通过 Jasmine 测试的文件。创建 JavaScript 文件后,在文件中附加以下代码集。

/*         
* This is the JavaScript file that need to be tested through jasmine   
* Below is the helloworld function that will return 'Hello World' 
*            
*/    

var helloworld = function() {   
   return 'Hello World'; 
}; 

第 4 步 − 创建测试用例

在此步骤中,我们将创建另一个 JavaScript 文件,该文件将包含上述 JavaScript 文件的测试用例。继续在"Spec"文件夹下创建一个 JavaScript 文件,并将其命名为 "HelloWorldsSpec.js"。将以下代码行添加到此 js 文件中。

/*            
* This is the file which will call our java script file that need to be tested. 
* Each describe block is equivalent to one test case    
*     
*/    

describe("Hello World", function() { 
   
   it("should Return Hello world",function() { 
      expect(helloworld()).toEqual('Hello World'); 
   }); 

});

第 5 步 − 添加对输出文件的引用

我们成功创建了我们自己的待测试文件和相应的测试用例。我们将其保存在两个不同的文件夹下。在此步骤中,我们将修改"SpecRunner.html"以包含这两个新创建的文件的引用。

<!DOCTYPE html> 
    
<html>    
   <head>    
      <meta charset = "utf-8"> 
    
      <title>Jasmine Spec Runner v2.4.1</title>  
		
      <link rel = "shortcut icon" type = "image/png" href = 
      "lib/jasmine2.4.1/jasmine_favicon.png">  
      <link rel = "stylesheet" href = "lib/jasmine-2.4.1/jasmine.css"> 
		
      <script src = "lib/jasmine-2.4.1/jasmine.js"></script>
      <script src = "lib/jasmine-2.4.1/jasmine-html.js"></script>
      <script src = "lib/jasmine-2.4.1/boot.js"></script> 

      <!--Lines to be deleted  
      <script src = "src/Player.js"></script> 
      <script src = "src/Song.js"></script> 
      <script src = "spec/SpecHelper.js"></script>    
      <script src = "spec/PlayerSpec.js"></script> --> 

      <!--adding the reference of our newly created file ---> 

      <script src = "src/helloworld.js"></script> 
      <script src = "spec/HelloWorldsSpec.js"></script> 
   </head>   

   <body>   
   </body>   

</html>

步骤 6 − 通过运行 SpecRunner.html 执行

这是我们应用程序开发的最后一步。在您喜欢的任何浏览器中运行 SpecRunner.html。结果将显示以下屏幕截图。绿屏表示成功,而红色表示测试用例失败。

Result

步骤 7 − 了解失败案例

到目前为止,我们已经看到了 hello world 应用程序的成功测试用例。现在让我们看看如果出现问题并且测试失败会怎样。要实现失败案例,我们需要编写一个失败测试用例。要执行相同操作,我们将使用以下代码修改 helloworld.js 文件。

var helloworld = function () { 
   return ''; 
};  

// we are not returning any string whereas in the spec file 
//we are expecting a // string as "Hello World" 

上述代码肯定会失败,因为我们的 spec 文件没有获得 helloworld() 输出的预期字符串。以下 specRunner.html 文件的屏幕截图显示存在错误,其红色指示器显示错误。

Error

JasmineJS - BDD 架构

Jasmine 遵循行为驱动开发 (BDD) 框架。在了解 Jasmine 的工作原理之前,让我们先了解一下什么是 BDD 框架。

以下流程图描述了 BDD 框架的不同阶段。

BDD 框架

步骤 1 − 开始

在此阶段,我们将为 Jasmine 应用程序准备好环境。

步骤 2 − 编写失败测试

在此步骤中,我们将编写第一个测试用例。很明显,这个测试会失败,因为没有要测试的文件或函数。

步骤 3 −编写代码使其通过

在此阶段,我们将准备需要测试的 JavaScript 文件或函数。此阶段至关重要,因为我们需要确保在早期阶段准备的所有测试用例都将成功。

步骤 4 − 重构

重构是 BDD 模型的一个非常重要的阶段,我们需要为该特定应用程序或功能准备尽可能多的测试用例。

步骤 5 − 停止

如果一切顺利,那么您的应用程序必须已准备就绪并启动。因此,我们可以将此步骤视为 BDD 应用程序的结束。

示例

我们现在已经收集了一些有关 BDD 框架工作原理的知识。让我们看看 Jasmine 如何在 JavaScript 测试中遵循这个 BDD 框架。

如屏幕截图所示,我们需要使用 Jasmine 框架测试 Abc.js。SpecRunner.html 是输出文件,它将以 Spec.js(测试用例文件)、Abc.js(要测试的文件)、LIB 作为输入,并运行 spec 文件中的所有测试用例,并将结果呈现到浏览器中。

工作原理

Lib − 这些是内置的 JavaScript 文件,将有助于测试我们项目中使用的不同函数和其他 JavaScript 文件。

Spec.js(测试用例文件) − 这是包含测试任何 JavaScript 函数或文件所需的所有测试用例的 JavaScript 文件。在 BDD 方法中,我们将首先编写测试,因此这是需要首先更新的文件。这肯定会失败,因为我们的项目中没有可以测试的文件或函数。此文件可以无限次重构,直到所有功能都经过测试。

Abc.js(要测试的文件) − 这是包含您的功能的文件,将使用 Spec.js 和 Lib 文件对其进行单元测试。

SpecRunner.html − SpecRunner.html 是一个普通的 html 文件,它将在其中嵌入的 JavaScript 代码的帮助下呈现单元测试的输出。

JasmineJS - 测试构建块

在本章中,我们将讨论 Jasmine 测试的构建块。

套件块

Jasmine 是一个 JavaScript 测试框架。套件 是 Jasmine 框架的基本构建块。为特定文件或函数编写的类似类型测试用例的集合称为一个套件。它包含另外两个块,一个是 "Describe()",另一个是 "It()"

一个套件块只能有两个参数,一个是 "该套件的名称",另一个是 "函数声明",它实际上调用了我们要测试的单元功能。

在下面的示例中,我们将创建一个套件,它将对 add.js 文件中的 add 函数进行单元测试。在这个例子中,我们有一个名为"calculator.js"的 JS 文件,它将通过 Jasmine 进行测试,相应的 Jasmine 规范文件是"CalCulatorSpec.js"

Calculator.js

window.Calculator = { 
   
   currentVal:0,  
   varAfterEachExmaple:0, 
   
   add:function (num1) { 
      this.currentVal += num1; 
      return this.currentVal;    
   },     
   
   addAny:function () {    
      var sum = this.currentVal; 
		
      for(var i = 0; i < arguments.length; i++) { 
         sum += arguments[i]; 
      } 
      
      this.currentVal = sum; 
      Return  this.currentVal; 
   }, 
};

CalCulatorSpec.js

describe("calculator",function() { 
   
   //test case: 1  
   it("Should retain the current value of all time", function () {
      expect(Calculator.currentVal).toBeDefined();
      expect(Calculator.currentVal).toEqual(0);  
   }); 
   
   //test case: 2  
   it("should add numbers",function() {
      expect(Calculator.add(5)).toEqual(5); 
      expect(Calculator.add(5)).toEqual(10);  
   });         
    
   //test case :3   
   it("Should add any number of numbers",function () {
      expect(Calculator.addAny(1,2,3)).toEqual(6); 
   }); 
}); 

在上述函数中,我们声明了两个函数。函数 add 将添加作为该函数的参数给出的两个数字,而另一个函数 addAny 应该添加作为参数给出的任何数字。

创建此文件后,我们需要将此文件添加到 head 部分内的 "SpecRunner.html" 中。成功编译后,将生成以下输出。

Calculatorspec

嵌套套件块

套件块可以在另一个套件块内包含多个套件块。以下示例将向您展示如何在另一个套件块内创建不同的套件块。我们将创建两个 JavaScript 文件,一个名为 "NestedSpec.js",另一个名为 "nested.js"

NestedSpec.js

describe("nested",function() { 
   
   // Starting of first suite block  
   // First block    
	
   describe("Retaining values ",function () {
   
      //test case:1    
      it ("Should retain the current value of all time", function () { 
         expect(nested.currentVal).toBeDefined();   
         expect(nested.currentVal).toEqual(0);   
      });    
   }); //end of the suite block   

   //second suite block 
   describe("Adding single number ",function () {     
   
      //test case:2 
      it("should add numbers",function() { 
         expect(nested.add(5)).toEqual(5); 
         expect(nested.add(5)).toEqual(10); 
      });         
   }); //end of the suite block  

   //third suite block 
   describe("Adding Different Numbers",function () {  
   
      //test case:3 
      it("Should add any number of numbers",function() {  
         expect(nested.addAny(1,2,3)).toEqual(6);  
      });    
   }); //end of the suite block 
});

Nested.js

window.nested = { 
   
   currentVal: 0,
	
   add:function (num1) {  
      this.currentVal += num1;     
      return this.currentVal;    
   },
   
   addAny:function () { 
      Var sum = this.currentVal; 
		
      for(var i = 0;i < arguments.length; i++) { 
         sum += arguments[i]; 
      } 
		
      this.currentVal = sum; 
      return this.currentVal;    
   }  
};

将上述代码段添加到 head 部分后,运行 specRunner.html 文件将生成以下输出。

SpecRunner Result

Describe 块

如前所述,describe 块是 Suite 块的一部分。与 Suite 块一样,它包含两个参数,一个是 "describe 块的名称",另一个是 "函数声明"。在我们接下来的示例中,我们将介绍许多 describe 块,以了解 Jasmine suite 块的工作流程。以下是一个完整的 describe 块的示例。

describe("Adding single number ",function () { 
   
   it("should add numbers",function() { 
      expect(nested.add(5)).toEqual(5); 
      expect(nested.add(5)).toEqual(10); 
   });     
}

IT 块

与 describe 块一样,我们也介绍了 IT 块。它位于 describe 块内。这是实际包含每个单元测试用例的块。在下面的代码中,一个 describe 块内有 IT 块的片段。

describe("Adding single number ",function () { 
   
   // test case : 1   
   it("should add numbers",function() {  
      expect(nested.add(5)).toEqual(5); 
      expect(nested.add(5)).toEqual(10); 
   });         
    
   //test case : 2 
   it("should add numbers",function() { 
      expect(nested.addAny(1,2,3)).toEqual(6); 
   });     
}

Expect 块

Jasmine Expect 允许您从所需函数或 JavaScript 文件中编写您的期望。它属于 IT 块。一个 IT 块可以有多个 Expect 块。

以下是 Expect 块的示例。此 Expect 块提供了多种方法来对您的 JavaScript 函数或 JavaScript 文件进行单元测试。每个 Expect 块也称为 匹配器。有两种不同类型的匹配器,一种是 内置匹配器,另一种是 用户定义匹配器

describe("Adding single number ",function () {   
   
   // test case : 1 
   it("should add numbers",function() {
      expect(nested.add(5)).toEqual(5); 
      expect(nested.add(5)).toEqual(10);
   });          
   
   //test case : 2 
   it("should add numbers",function() {
      expect(nested.addAny(1,2,3)).toEqual(6); 
   });     
}

在接下来的章节中,我们将讨论 Expect 块的不同内置方法的各种用途。

JasmineJS - Matchers

Jasmine 是一个测试框架,因此它始终旨在将 JavaScript 文件或函数的结果与预期结果进行比较。Matcher 在 Jasmine 框架中的工作方式类似。

Matchers 是 JavaScript 函数,它在实际输出和预期输出之间进行布尔比较。有两种类型的匹配器内置匹配器自定义匹配器

内置匹配器

Jasmine 框架中内置的匹配器称为内置匹配器。用户可以轻松地隐式使用它。

以下示例展示了内置匹配器在 Jasmine 框架中的工作方式。我们在上一章中已经使用过一些匹配器。

describe("Adding single number ", function () {  

   //example of toEqual() matcher    
   it("should add numbers",function() { 
      expect(nested.add(5)).toEqual(5); 
      expect(nested.add(5)).toEqual(10); 
   });   
   
   it("should add numbers",function() { 
      expect(nested.addAny(1,2,3)).toEqual(6); 
   });
}

示例中的 toEqual() 是内置匹配器,它将比较 add()addAny() 方法的结果与传递给 toEqual() 匹配器的参数。

自定义匹配器

Jasmine 内置系统库中不存在的匹配器称为 自定义匹配器。自定义匹配器需要 explicitly() 定义。在下面的示例中,我们将看到自定义匹配器的工作原理。

describe('This custom matcher example', function() {
   
   beforeEach(function() { 
      // 我们应该在 beforeEach() 函数中添加自定义匹配。
      jasmine.addMatchers ({ 
         validateAge: function() { 
            Return {    
               compare: function(actual,expected) {
                  var result = {}; 
                  result.pass = (actual > = 13 && actual < = 19);
                  result.message = 'sorry u are not a teen ';
                  return result; 
               }   
            };   
         }    
      });    
   }); 
    
   it('Lets see whether u are teen or not', function() { 
      var myAge = 14; 
      expect(myAge).validateAge();         
   });   
    
   it('Lets see whether u are teen or not ', function() { 
      var yourAge = 18;
      expect(yourAge).validateAge();  
   });
});

在上面的例子中,validateAge() 充当匹配器,它实际上是在某个范围内验证您的年龄。在此示例中,validateAge() 充当自定义匹配器。将此 JS 文件添加到 SpecRunner.html 并运行。它将生成以下输出。

ValidateAge

JasmineJS - 跳过块

Jasmine 还允许开发人员跳过一个或多个测试用例。这些技术可以应用于 Spec 级别Suite 级别。根据应用程序级别,此块可分别称为 Skipping SpecSkipping Suite

在下面的例子中,我们将学习如何使用 "x" 字符跳过特定的 SpecSuite

Skipping Spec

我们将在 it 语句之前使用 "x" 修改前面的示例。

describe('This custom matcher example ', function() { 
   
   beforeEach(function() { 
      // 我们应该在 beforeEach() 函数中添加自定义匹配。
      
      jasmine.addMatchers({ 
         validateAge: function() { 
            return { 
               compare: function(actual,expected) { 
                 var result = {}; 
                 result.pass = (actual > = 13 && actual < = 19); 
                 result.message = 'sorry u are not a teen ';  
                 return result; 
               }  
            };   
         }    
      });    
   });  
    
   it('Lets see whether u are teen or not', function() { 
      var myAge = 14; 
      expect(myAge).validateAge();  
   });
   
   xit('Lets see whether u are teen or not ', function() {  
      //Skipping this Spec 
      var yourAge = 18; 
   });
});

如果我们运行此 JavaScript 代码,我们将在浏览器中收到以下输出结果。Jasmine 本身将使用 "xit" 通知用户特定的 it 块已暂时 禁用

XIT Block Result

跳过套件

以同样的方式,我们可以禁用 describe 块以实现 跳过套件 的技术。在下面的示例中,我们将了解跳过套件块的过程。

xdescribe('This custom matcher example ', function() {  
   
   //Skipping the entire describe  block  
   beforeEach(function() {  
   
      // 我们应该在 beforeEach() 函数中添加自定义匹配。 
      jasmine.addMatchers({  
         validateAge: function() {  
            return {   
               compare: function(actual,expected) {  
                 var result = {}; 
                 result.pass = (actual >=13 && actual<=19); 
                 result.message ='sorry u are not a teen '; 
                 return result;  
               }   
            };   
         }   
      });   
   });

   it('Lets see whether u are teen or not', function() {  
      var myAge = 14; 
      expect(myAge).validateAge(); 
   });  

   it('Lets see whether u are teen or not ', function() {  
      var yourAge = 18; 
      expect(yourAge).validateAge(); 
   });
});

上述代码将生成以下屏幕截图作为输出。

Skipping Suite

正如我们在消息栏中看到的,它显示两个 spec 块处于待处理状态,这意味着这两个 Spec 块已使用 "x" 字符禁用。在下一章中,我们将讨论不同类型的 Jasmine 测试场景。

JasmineJS - 相等性检查

Jasmine 提供了大量方法来帮助我们检查任何 JavaScript 函数和文件的相等性。以下是一些检查相等性条件的示例。

ToEqual()

ToEqual() 是 Jasmine 内置库中最简单的匹配器。它只是匹配作为该方法的参数给出的操作结果是否与其结果匹配。

以下示例将帮助您了解此匹配器的工作原理。我们有两个要测试的文件,分别名为"expectexam.js",另一个需要测试的文件是"expectSpec.js"

Expectexam.js

window.expectexam = {    
   currentVal: 0,   
};

ExpectSpec.js

describe("Different Methods of Expect Block",function () { 
   
   it("The Example of toEqual() method",function () {   
      //this will check whether the value of the variable  
      // currentVal is equal to 0 or not.  
      expect(expectexam.currentVal).toEqual(0);  
   });
});

成功执行后,这些代码片段将产生以下输出。请记住,您需要按照前面的示例指示,将这些文件添加到 specRunner.html 文件的标头部分。

toEquals Method

not.toEqual()

not.toEqual() 的作用与 toEqual() 完全相反。当我们需要检查值是否与任何函数的输出不匹配时,使用 not.toEqual()

我们将修改上述示例以展示其工作原理。

ExpectSpec.js

describe("Different Methods of Expect Block",function () { 

   it("The Example of toEqual() method",function () {
      expect(expectexam.currentVal).toEqual(0);  
   });   
   
   it("The Example of not.toEqual() method",function () {  
      //negation  testing expect(expectexam.currentVal).not.toEqual(5); 
   }); 
});

Expectexam.js

window.expectexam = { 
   currentVal: 0,  
}; 

在第二个 expect 块中,我们检查 currentVal 的值是否等于 5,因为 currentVal 的值为零,因此我们的测试通过并为我们提供了绿色输出。

notEquals Method

ToBe()

toBe() 匹配器的工作方式与 toEqual() 类似,但它们在技术上彼此不同。toBe() 匹配器与对象的类型匹配,而 toEqual() 与结果的等价性匹配。

以下示例将帮助您了解 toBe() 匹配器的工作原理。此匹配器与 JavaScript 的"==="运算符完全等同,而 toEqual() 与 JavaScript 的"=="运算符类似。

ExpectSpec.js

describe("Different Methods of Expect Block",function () {  

   it("The Example of toBe() method",function () { 
      expect(expectexam.name).toBe(expectexam.name1);     
   });
});

Expectexam.js

window.expectexam = {
   currentVal: 0, 
   name:"tutorialspoint", 
   name1:tutorialspoint  
};

我们将稍微修改我们的 expectexam JavaScript 文件。我们添加了两个新变量,namename1。请找出这两个添加的变量之间的区别 - 一个是字符串类型,另一个不是字符串类型。

以下屏幕截图是我们的测试结果,其中红叉表示这两个值不相等,而预期它们应该相等。因此我们的测试失败。

expectExam Error

让我们将两个变量 namename1 转换为字符串类型变量,然后再次运行相同的 SpecRunner.html。现在检查输出。它将证明 toBe() 不仅与变量的等价性匹配,而且还与变量的数据类型或对象类型匹配。

not.toBe()

如前所述,not 只不过是 toBe() 方法的否定。当预期结果与函数或 JavaScript 文件的实际输出匹配时,它会失败。

以下是一个简单的示例,可帮助您了解 not.toBe() 匹配器的工作原理。

describe("Different Methods of Expect Block",function () { 
   it("The Example of not.toBe() method",function () { 
      expect(true).not.toBe(false);    
   });
});

此处 Jasmine 将尝试将 true 与 false 匹配。由于 true 不能与 false 相同,因此此测试用例将有效并通过。

toBe Method

JasmineJS - 布尔检查

除了相等性检查外,Jasmine 还提供了一些方法来检查布尔条件。以下是帮助我们检查布尔条件的方法。

ToBeTruthy()

此布尔匹配器在 Jasmine 中用于检查结果是 true 还是 false。

以下示例将帮助我们了解 toBeTruthy() 函数的工作原理。

ExpectSpec.js

describe("Different Methods of Expect Block",function () {
   it("The Example of toBeTruthy() method",function () {   
      expect(expectexam.exampleoftrueFalse(5)).toBeTruthy();    
   });
}); 

Expectexam.js

window.expectexam = {  
   exampleoftrueFalse: function (num) {  
      if(num < 10)    
         return true;  
      else   
         return false;  
   },  
};

由于我们传递的数字 5 小于 10,因此此测试用例将通过并给出以下输出。

toBeTruthy Method

如果我们传递的数字大于 10,则此绿色测试将变为红色。在第二个屏幕截图中,您可以看到,在传递某个大于 10 的值时,预期的测试用例失败并生成红色输出,表明"预期 false 为 truthy"。

toBeTruthy Error

toBeFalsy()

toBeFalsy() 的工作方式也与 toBeTruthy() 方法相同。它将输出匹配为 false,而 toBeTruthy 将输出匹配为 true。下面的例子将帮助你理解toBeFalsy()的基本工作原理。

ExpectSpec.js

describe("Different Methods of Expect Block",function() { 
   it("The Example of toBeTruthy() method",function () {
      expect(expectexam.exampleoftrueFalse(15)).toBeFalsy();   
   });
});

Expectexam.js

window.expectexam = {  
   exampleoftrueFalse: function (num) {  
      if(num < 10)    
         Return true;  
      else   
         return false; 
   },
}; 

上面的代码将通过 Jasmine 测试用例,因为我们传递的值大于 10,并且预期输出为 false。因此,浏览器将显示一个绿色标志,表示已通过。

toBeTruthy Method

JasmineJS - 顺序检查

Jasmine 还提供了不同的方法来提供 JS 输出的顺序性。以下示例展示了如何使用 Jasmine 实现顺序检查。

ToContain()

toContain() 匹配器为我们提供了检查任何元素是否是同一数组或其他顺序对象的一部分的功能。以下示例将帮助我们了解 Jasmine toContain() 方法的工作方法。让我们在之前创建的 customerMatcherSpec.js 文件中添加以下一段代码。

describe("Different Methods of Expect Block",function () {  
   it("The  Example of toContain() method",function () { 
      expect([1,2, 3, 4]).toContain(3);
   });
}); 

在上面的例子中,我们检查 3 是否存在于该数组中。我们得到绿色输出,因为 3 存在于数组中。

toContain Method

在上面的例子中,让我们将 3 的值更改为 15,然后再次运行规范。我们将得到以下红色屏幕,因为 15 不属于我们作为该函数的参数传递的数组。

toContain Error

ToBeCloseTo()

toBeCloseTo() 匹配器匹配实际值是否接近预期值。在以下示例中,我们将修改 customerMatcherSpec.js 文件并查看其实际工作原理。

describe("Different Methods of Expect Block", function () {  
   it("Example of toBeCloseTo()", function () { 
      expect(12.34).toBeCloseTo(12.3, 1);    
   });
});

在上面的 Describe 块中,我们检查实际结果"12.3"是否更接近预期输出"12.34"。由于这满足了我们的要求,我们将得到以下绿色屏幕截图作为输出。此方法的第二个参数是要比较的小数位数。

toBeCloseTo Method

在上面的代码中,让我们将预期值修改为 15 并运行 SpecRunner.html

describe("Different Methods of Expect Block",function () { 
   it("Example of  toBeCloseTo()", function () { 
      expect(12.34).toBeCloseTo(15, 1);
   });
}); 

在这种情况下,15 远远不及 15,因此会产生错误,并显示红色屏幕截图作为错误。

toBeCloseTo Error

ToMatch()

ToMatch() 匹配器适用于字符串类型变量。它有助于确定特定字符串是否存在于预期输出中。以下是我们的 customerMatcherSpec.js 的样子。

describe("Different Methods of Expect Block",function () { 
   it("Example of toMatch()", function () { 
      expect("Jasmine tutorial in tutorials.com").toMatch(/com/);   
   });
});

这段代码将测试 "com" 是否存在于给定的预期字符串中。由于 com 存在于字符串中,它将生成绿色屏幕截图并通过测试条件。

toMatch Method

现在让我们将输出更改为其他字符串,该字符串不存在于预期值中。然后我们的 customerMatcherSpec.js 将如下所示。

describe("Different Methods  of Expect Block",function () { 
   it("Example of toMatch()", function () { 
      expect("Jasmine tutorial in tutorials.com").toMatch(/XYZ/);
   });
}); 

上述代码将在预期值中找到"XYZ"字符串。由于预期字符串中不存在该字符串,因此将抛出错误,输出屏幕将相应地显示为红色。

toMatch Error

JasmineJS - Null 检查

Jasmine 提供了多种方法来检查实际输出是否为 Null、已定义或未定义。在本章中,我们将学习如何实现不同的 Jasmine 方法来检查上述场景。

ToBedefined()

此匹配器用于检查代码中的任何变量是否已预定义。让我们根据此示例修改我们的 customerMatcherSpec.js 文件。

currentVal = 0;  

describe("Different Methods  of Expect Block",function () { 
   it("Example of  toBeDefined", function () {
      expect(currentVal).toBeDefined();
   });
});

在上面的代码中,toBeDefined() 将检查变量 currentVal 是否在系统中定义。由于 currentVal 在开始时定义为 0,因此此测试将通过并生成绿色屏幕截图作为输出。

toBeDefined Method

再次在上述示例中,让我们删除第一行,其中我们实际定义了"currentVal",然后再次运行。然后我们将看到一个红色屏幕,这意味着测试实际上失败了,因为我们期望定义一个未定义的值。以下屏幕截图将是输出文件。

toBeDefined Error

ToBeUndefined()

此匹配器有助于检查任何变量是否先前未定义,基本上它与之前的匹配器 toBeDefined 的工作方式完全相反。在下面的示例中,我们将学习如何使用此匹配器。让我们使用以下条目修改我们的 Spec 文件,即 customerMatcher.js 文件。

describe("Different Methods of Expect Block",function () { 
   it("Example of toBeUndefine()", function () { 
      var undefineValue; 
      expect(undefineValue).toBeUndefined(); 
   });
}); 

在上面的部分中,我们将验证我们的变量 "undefineValue" 是否确实未定义。将此文件添加到 SpecRunner 后,我们将收到一个绿色屏幕截图作为输出,这告诉我们该值实际上之前未定义。

toBeUndefine Method

让我们再次用一些预定义值定义变量,看看它是否会引发错误。新的 customerMatcher.js 如下所示。

describe("Different Methods of Expect Block",function () {
   it("Example oftoBeUndefine()", function () { 
      var undefineValue = 0;
      expect(undefineValue).toBeUndefined();
   });
});

上面的代码会抛出一个错误并生成一个红色的截图,因为我们已经将"undefineValue"值定义为"0"并且期望它未被定义。运行SpecRunner.html文件时将生成以下截图。

toBeUndefine Error

toBeNull()

顾名思义,此匹配器有助于检查空值。让我们再次使用以下代码修改我们的customerMatcherSpec.js文件。

describe("Different Methods of Expect Block",function () { 
   var value = null; 
	
   it("Example of toBeNull()", function () { 
      expect(value).toBeNull();
   });
}); 

在上面的代码中,我们提到了一个变量"value",并且明确指出这个值为 null。在 expect 块中,toBeNull() 匹配器将检查这个值并相应地给出结果。以下是在 SpecRunner.html 文件的帮助下运行上述代码时的输出。

toBeNull Method

现在让我们通过提供除 null 之外的一些定义值进行测试。请相应地修改 customerMatcher.js 文件。

describe("Different Methods of Expect Block",function () {
   var value = "TutorialsPoint"; 
	
   it("Example of  toBeNull()", function () { 
      expect(value).toBeNull();
   });
}); 

在上面的例子中,我们用"TutorialsPoint"修改了变量值,它不是空值。因此,此测试将失败并产生红色屏幕截图作为输出。

toBeNull Error

JasmineJS - 不等式检查

到目前为止,我们已经讨论了 Jasmine 中的不同方法,这些方法可帮助我们根据需求测试不同的场景。在本章中,我们将了解不同的匹配器,它们将帮助我们检查 JS 文件中的不等式条件。以下是用于此目的的匹配器。

ToBeGreaterThan()

顾名思义,此匹配器有助于检查大于条件。让我们使用以下代码修改我们的 customerMatcher.js

describe("Different Methods of Expect Block",function () { 
   var exp = 8;  
	
   it("Example of  toBeGreaterThan()", function () {
      expect(exp).toBeGreaterThan(5);
   });
}); 

在上面这段代码中,我们期望变量 "exp" 的值大于 5。现在,由于变量"exp"的值为"8",大于"5",这段代码将生成绿色屏幕截图。

Greaterthan Method

现在让我们再次将变量的值修改为"4",并使此测试失败。为此,我们需要使用以下代码修改 js 文件。

describe("Different Methods of Expect Block",function () {  
   var exp = 4;  
	
   it ("Example of toBeGreaterThan()", function () {
      expect(exp).toBeGreaterThan(5); 
   });
});

此代码将失败,因为值 4 不能大于 5。因此它将产生以下输出。

Greaterthan Error

ToBeLessThan()

此匹配器有助于检查测试场景的小于条件。它的行为与 toBeGreaterThan() 匹配器的行为完全相反。现在让我们看看这个匹配器是如何工作的。让我们相应地修改 customerMatcher.js 文件。

describe("Different Methodsof Expect Block",function () { 
   var exp = 4;  
	
   it("Example of toBeLessThan()", function() { 
      expect(exp).toBeLessThan(5);    
   });
}); 

与前面的示例一样,我们有一个变量,其值为"4"。在这段代码中,我们检查此变量的值是否小于 5。这段代码将生成以下输出。

Lessthan Method

现在,为了使此操作失败,我们需要为变量 exp 分配一些更大的数字。让我们这样做并测试应用程序。我们将 25 作为 exp 的值,这肯定会引发错误并产生以下红色屏幕截图。

Lessthan Error

JasmineJS - 不是数字检查

Jasmine 提供了一个特殊的匹配器来检查这种特殊类型的测试场景,即 toBeNaN()

让我们用以下代码修改我们的 customerMatcher.js

describe("Different Methods of Expect Block",function () { 
   it("Example of toBeNaN()", function () { 
      expect(0 / 0).toBeNaN(); 
   });
});

这里我们想测试"0/0"的值,但无法确定。因此,这段代码将生成以下绿色屏幕截图。

toBeNan

现在让我们再次使用以下逻辑修改代码,我们将一个变量exp赋值为25,并期望结果不是用1除以5得到的结果。

describe("Different Methods of Expect Block",function () { 
   var exp = 25; 
	
   it("Example of toBeNaN()", function () { 
      expect(exp/5).toBeNaN(); 
   });
});

这段代码将产生以下输出。

toBeNan Output

JasmineJS - 异常检查

除了不同的计算匹配器外,Jasmine 还提供了一些有用的匹配器来检查程序的异常。让我们用以下一组代码修改我们的 JavaScript。

var throwMeAnError = function() {   
   throw new Error(); 
};  

describe("Different Methods of Expect Block", function() {  
   var exp = 25; 

   it ("Hey this will throw an Error ", function() { 
      expect(throwMeAnError).toThrow(); 
   }); 
});

在上面的例子中,我们创建了一个故意从该方法抛出异常的方法,并且在 expect 块中我们期望捕获该错误。如果一切顺利,那么这段代码将产生以下输出。

Exception Block

现在,要使此测试用例失败,我们需要在函数 throwMeAnError 中省略该 throw 语句。以下是将产生红色屏幕截图作为输出的代码,因为代码不满足我们的要求。

var throwMeAnError = function() {   
   //throw new Error(); 
};   

describe("Different Methods of Expect Block",function() {  
   var exp = 25; 
   
   it("Hey this will throw an Error ", function() {  
      expect(throwMeAnError).toThrow();    
   }); 
});

如您所见,我们已经注释掉了方法抛出异常的那一行。以下是成功执行 SpecRunner.html 后上述代码的输出。

Exception Error

Jasmine.Any()

Any 是当我们不确定输出时使用的特殊匹配器。在下面的示例中,我们将了解其工作原理。让我们使用以下代码修改 customerMatcher.js

var addAny = function() {
   var sum = this.currentVal; 
	
   for (var i = 0; i < arguments.length; i++) { 
      sum += arguments[i]; 
   } 
	
   this.currentVal = sum;  
   return this.currentVal; 
} 

describe("Different Methods of Expect Block",function () { 
   
   it("Example of any()", function() { 
      expect(addAny(9,9)).toEqual(jasmine.any(Number)); 
   });
});

这里我们声明了一个函数,它将为我们提供作为参数提供的数字的总和。在期望块中,我们期望结果可以是任何东西,但它应该是一个数字。

由于 9 和 sum 之后的 9 都是数字,因此此测试将通过,并将生成以下绿色屏幕截图作为输出。

Any Method

现在让我们根据以下代码更改代码,其中我们期望字符串类型变量作为函数 AddAny() 的输出。

var addAny = function() {
   var sum = this.currentVal; 
	
   for(var i = 0; i < arguments.length; i++) { 
      sum += arguments[i]; 
   } 
	
   this.currentVal = sum; 
   return this.currentVal; 
}  

describe("Different Methodsof Expect Block",function () { 
   it("Example of any()", function () { 
      expect(addAny(9,9)).toEqual(jasmine.any(String));    
   });
});

以下是上述代码的输出。

Any Error

JasmineJS - beforeEach()

Jasmine 的另一个值得注意的功能是每个函数之前和之后。使用这两个功能,我们可以在执行每个规范之前和之后执行一些代码片段。此功能对于在应用程序中运行通用代码非常有用。让我们创建一个如下所示的规范文件。

var currentVal = 0; 

beforeEach(function() { 
   currentVal = 5; 
});  

describe("Different Methods of Expect Block",function() { 
   it("after each function ", function() {
      expect(currentVal).toEqual(5);     
   });
});

虽然我们在开始时将一个变量声明为"0",但我们期望该值在期望块中应等于 5。上面的代码将生成以下输出。

BeforeEach

在上面的代码中,在执行期望块之前,将 5 分配给变量 currentVal。因此,它会生成一个没有错误的绿色屏幕截图。

JasmineJS - afterEach()

与 beforeEach() 一样,afterEach() 的工作方式完全相同。它在 spec 块执行后执行。让我们使用以下代码修改前面的示例。

var currentVal = 0; 

afterEach(function() { 
   currentVal = 5;  
});  

describe("Different Methods of Expect Block",function() { 
   it("first call ", function() { 
      expect(currentVal).toEqual(0);     
   });     
   
   it("second call ",  function() { 
      expect(currentVal).toEqual(5);     
   });
});

在上面的例子中,在运行第一个 spec 块时,currentVal 的值为 0。因此,它将通过测试用例,但在运行第一个 it 块后,Jasmine 编译运行了 afterEach() 块,这使 currentVal 的值为 5。因此,它也满足第二种情况并产生绿色屏幕截图作为输出。

AfterEach

JasmineJS - Spies

Jasmine Spies是另一个功能,其功能与其名称指定完全相同。它将允许您监视应用程序函数调用。Jasmine 中有两种类型的Spies技术。第一种方法可以使用 spyOn() 实现,第二种方法可以使用 createSpy() 实现。在本章中,我们将进一步了解这两种方法。

spyOn()

spyOn() 内置于 Jasmine 库中,可让您监视特定代码段。让我们创建一个新的 spec 文件"spyJasmineSpec.js"和另一个名为"spyJasmine.js"的 js 文件。以下是这两个文件的条目。

SpyJasmine.js

var Person = function() {}; 

Person.prototype.sayHelloWorld = function(dict) { 
   return dict.hello() + " " + dict.world(); 
}; 

var Dictionary = function() {}; 

Dictionary.prototype.hello = function() { 
   return "hello"; 
}; 

Dictionary.prototype.world = function() { 
   return "world"; 
}; 

SpyJasmineSpec.js

describe("Example Of jasmine Spy using spyOn()", function() { 
  
   it('uses the dictionary to say "hello world"', function() { 
      var dictionary = new Dictionary; 
      var person = new Person; 
		
      spyOn(dictionary, "hello");  // replace hello function with a spy 
      spyOn(dictionary, "world");  // replace world function with another spy 
		
      person.sayHelloWorld(dictionary);
      expect(dictionary.hello).toHaveBeenCalled();  
      // not possible without first spy 
  
      expect(dictionary.world).toHaveBeenCalled();  
      // not possible withoutsecond spy 
   }); 
});

在上面这段代码中,我们希望 person 对象说"Hello world",但我们也希望 person 对象应该咨询字典对象,以便为我们提供输出文字"Hello world"。

查看 Spec 文件,您可以看到我们使用了 spyOn() 函数,它实际上模仿了 helloworld 函数的功能。因此,我们实际上不是在调用该函数,而是在模仿函数调用。这是 Spies 的专长。上面的代码将产生以下输出。

spyOn Method

createSpy()

获取Spies功能的另一种方法是使用 createSpy()。让我们使用以下代码修改我们的两个 js 文件。

SpyJasmine.js

var Person = function() {};    

Person.prototype.sayHelloWorld = function(dict) { 
   return dict.hello() + " " + dict.world(); 
}; 

var Dictionary = function() {}; 

Dictionary.prototype.hello = function() { 
   return "hello"; 
}; 

Dictionary.prototype.world = function() { 
   return "world"; 
}; 

SpyJasmineSpec.js

describe("Example Of jasmine Spy using Create Spy", function() { 
   
   it("can have a spy function", function() { 
      var person = new Person(); 
      person.getName11 = jasmine.createSpy("Name spy"); 
      person.getName11(); 
      expect(person.getName11).toHaveBeenCalled(); 
   }); 
}); 

查看 spec 文件,我们正在调用 Person 对象的 getName11()。虽然 spy Jasmine.js 中的 person 对象中不存在此函数,但我们没有收到任何错误,因此输出为绿色且为正值。在此示例中,createSpy() 方法实际上模仿了 getName11() 的功能。

上述代码将生成以下输出。

CreateSpy