国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
模擬服務
模擬提供程序
模擬模塊
模擬返回 Promise 的方法
模擬全局對象
在 AngularJS 測試中模擬依賴項的目的是什麼?
如何在 AngularJS 中創(chuàng)建一個模擬服務?
首頁 web前端 js教程 AngularJS測試中的模擬依賴項

AngularJS測試中的模擬依賴項

Feb 20, 2025 pm 12:28 PM

Mocking Dependencies in AngularJS Tests

核心要點

  • AngularJS 天生就考慮到了測試,其內置的依賴注入機制使得每個組件都可使用任何 JavaScript 測試框架(如 Jasmine)進行測試。
  • 單元測試中的模擬涉及隔離測試代碼片段的功能,這可能具有挑戰(zhàn)性,因為依賴項來自不同的來源。 AngularJS 中的模擬通過 angular-mocks 模塊簡化了,該模塊為一組常用的 AngularJS 服務提供了模擬。
  • AngularJS 中的服務模擬可以通過獲取實際服務的實例並偵聽服務的方法,或者使用 $provide 實現(xiàn)模擬服務來完成。後者方法更可取,可以避免調用服務的實際方法實現(xiàn)。
  • AngularJS 中的提供程序模擬遵循與服務模擬類似的規(guī)則。測試中必須實現(xiàn) $get 方法。如果測試文件中不需要 $get 函數中定義的功能,則可以將其賦值為空函數。
  • 全局對象(例如全局“window”對象的一部分或由第三方庫創(chuàng)建的對象)可以通過注入它們到 $window 或使用全局對象創(chuàng)建值或常量並根據需要注入它們來實現(xiàn)模擬。

AngularJS 的設計理念中就包含了測試??蚣艿脑创a經過了非常充分的測試,並且使用該框架編寫的任何代碼也都是可測試的。內置的依賴注入機制使得用 AngularJS 編寫的每個組件都可進行測試。 AngularJS 應用程序中的代碼可以使用任何現(xiàn)有的 JavaScript 測試框架進行單元測試。最常用於測試 AngularJS 代碼的框架是 Jasmine。本文中的所有示例代碼片段都是使用 Jasmine 編寫的。如果您在 Angular 項目中使用任何其他測試框架,您仍然可以應用本文中討論的思想。

本文假設您已經具備單元測試和測試 AngularJS 代碼的經驗。您不必是測試專家。如果您對測試有基本的了解,並且可以為 AngularJS 應用程序編寫一些簡單的測試用例,那麼您可以繼續(xù)閱讀本文。

模擬在單元測試中的作用

每個單元測試的任務都是隔離地測試一段代碼的功能。隔離被測系統(tǒng)有時可能具有挑戰(zhàn)性,因為依賴項可能來自不同的來源,我們需要充分理解要模擬的對象的職責。

在 JavaScript 等非靜態(tài)類型語言中,模擬很困難,因為不容易理解要模擬的對象的結構。同時,它也提供了靈活性,即僅模擬被測系統(tǒng)當前正在使用的對象的某一部分,而忽略其餘部分。

AngularJS 測試中的模擬

由於 AngularJS 的主要目標之一是可測試性,核心團隊為此付出了額外的努力,使測試更容易,並在 angular-mocks 模塊中為我們提供了一組模擬。此模塊包含圍繞一組 AngularJS 服務(例如 $http、$timeout、$animate 等)的模擬,這些服務廣泛用於任何 AngularJS 應用程序中。此模塊減少了開發(fā)人員編寫測試所需的大量時間。

在為真實的業(yè)務應用程序編寫測試時,這些模擬非常有幫助。同時,它們不足以測試整個應用程序。我們需要模擬框架中但未被模擬的任何依賴項——來自第三方插件的依賴項、全局對像或在應用程序中創(chuàng)建的依賴項。本文將介紹一些關於模擬 AngularJS 依賴項的技巧。

模擬服務

服務是 AngularJS 應用程序中最常見的依賴項類型。您可能已經知道,服務在 AngularJS 中是一個重載的術語。它可能指服務、工廠、值、常量或提供程序。我們將在下一節(jié)討論提供程序。服務可以通過以下方式之一進行模擬:

  • 使用注入塊獲取實際服務的實例並偵聽服務的方法。
  • 使用 $provide 實現(xiàn)模擬服務。

我不喜歡第一種方法,因為它可能導致調用服務的實際方法實現(xiàn)。我們將使用第二種方法來模擬以下服務:

angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });

以下代碼片段創(chuàng)建了上述服務的模擬:

module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
  });
});

// 獲取模擬服務的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});

儘管上面的示例使用 Jasmine 創(chuàng)建間諜,但您可以使用 Sinon.js 替換它,實現(xiàn)等效的功能。

最好在加載測試所需的所有模塊後創(chuàng)建所有模擬。否則,如果在一個已加載的模塊中定義了一個服務,則實際實現(xiàn)會覆蓋模擬實現(xiàn)。

常量、工廠和值可以使用 $provide.constant$provide.factory$provide.value 分別進行模擬。

模擬提供程序

模擬提供程序類似於模擬服務。編寫提供程序時必須遵循的所有規(guī)則也必須在模擬它們時遵循??紤]以下提供程序:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });

以下代碼片段為上述提供程序創(chuàng)建了一個模擬:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 獲取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});

獲取提供程序和其他單例的引用的區(qū)別在於,提供程序在此時不會在 inject() 塊中可用,因為提供程序此時已轉換為工廠。我們可以使用 module() 塊獲取它們的對象。

在定義提供程序的情況下,測試中也必須實現(xiàn) $get 方法。如果您在測試文件中不需要 $get 函數中定義的功能,則可以將其賦值為空函數。

模擬模塊

如果要在測試文件中加載的模塊需要一堆其他模塊,則除非加載所有必需的模塊,否則無法加載被測模塊。加載所有這些模塊有時會導致測試失敗,因為某些實際的服務方法可能會從測試中調用。為了避免這些困難,我們可以創(chuàng)建虛擬模塊來加載被測模塊。

例如,假設以下代碼表示一個添加了示例服務的模塊:

angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });

以下代碼是示例服務的測試文件中的 beforeEach 塊:

module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
  });
});

// 獲取模擬服務的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});

或者,我們也可以將服務的模擬實現(xiàn)添加到上面定義的虛擬模塊中。

模擬返回 Promise 的方法

如果不使用 Promise,編寫端到端的 Angular 應用程序可能很困難。測試依賴於返回 Promise 的方法的代碼片段成為一項挑戰(zhàn)。普通的 Jasmine 間諜會導致某些測試用例失敗,因為被測函數會期望一個具有實際 Promise 結構的對象。

可以使用另一個返回具有靜態(tài)值的 Promise 的異步方法來模擬異步方法??紤]以下工廠:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });

我們將測試上述工廠中的 getData() 函數。正如我們所看到的,它依賴於服務 dataSourceSvc 的方法 getAllItems()。我們需要在測試 getData() 方法的功能之前模擬服務和方法。

$q 服務具有 when()reject() 方法,允許使用靜態(tài)值來解析或拒絕 Promise。這些方法在模擬返回 Promise 的方法的測試中非常有用。以下代碼片段模擬了 dataSourceSvc 工廠:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 獲取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});

$q Promise 在下一個 digest 週期後完成其操作。 digest 週期在實際應用程序中不斷運行,但在測試中則不會。因此,我們需要手動調用 $rootScope.$digest() 以強制執(zhí)行 Promise。以下代碼片段顯示了一個示例測試:

angular.module('first', ['second', 'third'])
  // util 和 storage 分別在 second 和 third 中定義
  .service('sampleSvc', function(utilSvc, storageSvc) {
    // 服務實現(xiàn)
  });

模擬全局對象

全局對象來自以下來源:

  1. 全局“window”對象的一部分的對象(例如,localStorage、indexedDb、Math 等)。
  2. 由第三方庫(如 jQuery、underscore、moment、breeze 或任何其他庫)創(chuàng)建的對象。

默認情況下,全局對象無法模擬。我們需要遵循某些步驟才能使它們可模擬。

我們可能不想模擬 Math 對像或 _(由 Underscore 庫創(chuàng)建)的實用程序對象,因為它們的操作不執(zhí)行任何業(yè)務邏輯、不操作 UI,也不與數據源通信。但是,必須模擬諸如 $.ajax、localStorage、WebSockets、breeze 和 toastr 之類對象。因為如果沒有模擬這些對象,這些對象會在執(zhí)行單元測試時執(zhí)行其實際操作,這可能會導致一些不必要的 UI 更新、網絡調用,有時還會導致測試代碼中的錯誤。

由於依賴注入,Angular 中編寫的每一部分代碼都是可測試的。 DI 允許我們傳遞任何遵循實際對象 shim 的對象,只是為了使被測代碼在執(zhí)行時不會中斷。如果可以注入全局對象,則可以模擬它們。有兩種方法可以使全局對象可注入:

  1. $window 注入到需要全局對象的 service/controller 中,並通過 $window 訪問全局對象。例如,以下服務通過 $window 使用 localStorage:
angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });
  1. 使用全局對象創(chuàng)建一個值或常量,並在需要的地方注入它。例如,以下代碼是 toastr 的常量:
module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模擬實現(xiàn)
    });
  });
});

// 獲取模擬服務的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});

我更喜歡使用常量而不是值來包裝全局對象,因為常量可以注入到配置塊或提供程序中,並且常量不能被裝飾。

以下代碼片段顯示了 localStorage 和 toastr 的模擬:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });

結論

模擬是在任何語言中編寫單元測試的重要組成部分之一。正如我們所看到的,依賴注入在測試和模擬中起著重要作用。代碼必須以一種方式組織,以便輕鬆測試其功能。本文列出了在測試 AngularJS 應用程序時模擬最常見的一組對象。與本文相關的代碼可從 GitHub 下載。

關於在 AngularJS 測試中模擬依賴項的常見問題解答 (FAQ)

在 AngularJS 測試中模擬依賴項的目的是什麼?

在 AngularJS 測試中模擬依賴項是單元測試的關鍵部分。它允許開發(fā)人員隔離被測代碼並模擬其依賴項的行為。這樣,您可以測試代碼如何與其依賴項交互,而無需實際調用它們。當依賴項複雜、緩慢或具有您希望在測試期間避免的副作用時,這尤其有用。通過模擬這些依賴項,您可以專注於在受控環(huán)境中測試代碼的功能。

如何在 AngularJS 中創(chuàng)建一個模擬服務?

在 AngularJS 中創(chuàng)建模擬服務涉及在模塊配置中使用 $provide 服務。您可以使用 $provide 服務的 valuefactoryservice 方法來定義服務的模擬實現(xiàn)。這是一個基本示例:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 獲取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});

在這個例子中,我們使用 $provide.value 方法來定義 myService 的模擬實現(xiàn)。在測試期間,將使用此模擬服務代替實際服務。

(其餘的FAQ問題,由於篇幅限制,請逐個提出,我會盡力提供簡潔明了的答案。)

以上是AngularJS測試中的模擬依賴項的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語言,各自適用於不同的應用場景。 Java用於大型企業(yè)和移動應用開發(fā),而JavaScript主要用於網頁開發(fā)。

JavaScript評論:簡短說明 JavaScript評論:簡短說明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

如何在JS中與日期和時間合作? 如何在JS中與日期和時間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時間處理需注意以下幾點:1.創(chuàng)建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區(qū)問題建議使用支持時區(qū)的庫,如Luxon。掌握這些要點能有效避免常見錯誤。

為什麼要將標籤放在的底部? 為什麼要將標籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScript與Java:開發(fā)人員的全面比較 JavaScript與Java:開發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

JavaScript:探索用於高效編碼的數據類型 JavaScript:探索用於高效編碼的數據類型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數設為true實現(xiàn);2.事件冒泡是默認行為,useCapture設為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態(tài)內容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應用戶操作的時機和方式。

Java和JavaScript有什麼區(qū)別? Java和JavaScript有什麼區(qū)別? Jun 17, 2025 am 09:17 AM

Java和JavaScript是不同的編程語言。 1.Java是靜態(tài)類型、編譯型語言,適用於企業(yè)應用和大型系統(tǒng)。 2.JavaScript是動態(tài)類型、解釋型語言,主要用於網頁交互和前端開發(fā)。

See all articles