AngularJS中的單元測試:服務,控制器和提供商
鑰匙要點
- angularJS的設計考慮了可檢驗性,使用依賴注入使單位測試更加容易,並允許將應用程序模塊化為不同組件,例如服務,控制器和提供商。 >
- > 在AngularJS中進行的 單元測試可能很棘手,但值得花時間,因為它可以確保應用程序的正確性。 Angularjs使使用框架編寫的測試代碼更加容易。
-
> 在本文中,我將分享有關AngularJS中測試服務,控制器和提供商的一組技巧。代碼片段是使用茉莉花編寫的,可以使用業力測試跑者運行。您可以從我們的GitHub Repo下載本文中使用的代碼,您還將在其中找到有關運行測試的說明。
測試服務
服務是AngularJS應用程序中最常見的組件之一。它們提供了一種在中心位置定義可重複使用的邏輯的方法,因此不需要一遍又一遍地重複相同的邏輯。該服務的單身性質使得可以通過多個控制器,指令甚至其他服務共享相同的數據。服務可以取決於一組其他服務來執行其任務。說,名為A的服務取決於服務B,C和D執行其任務。在測試服務a時,依賴項B,C和D必須用模擬替換。
>>我們通常會模擬所有依賴項,除了某些公用事業服務(例如$ rootscope和$ parse)。我們使用茉莉花(Jasmine.createspy()將在測試中必須檢查的方法(在茉莉花中稱為間諜)中必須檢查的方法,該間諜將返回全新的功能。
此服務只有一種方法(Showdialog)。根據輸入的值此方法收到的輸入值,它將將其註入依賴項($ window或modalsvc)中的兩個服務之一。
angular<span>.module('services', []) </span> <span>.service('sampleSvc', ['$window', 'modalSvc', function($<span>window, modalSvc</span>){ </span> <span>this.showDialog = function(message<span>, title</span>){ </span> <span>if(title){ </span> modalSvc<span>.showModalDialog({ </span> <span>title: title, </span> <span>message: message </span> <span>}); </span> <span>} else { </span> $<span>window.alert(message); </span> <span>} </span> <span>}; </span> <span>}]);</span>
>現在我們可以測試Showdialog方法的行為。我們可以為該方法編寫的兩個測試用例如下:
<span>var mockWindow, mockModalSvc, sampleSvcObj; </span><span>beforeEach(function(){ </span> <span>module(function($provide){ </span> $provide<span>.service('$window', function(){ </span> <span>this.alert= jasmine.createSpy('alert'); </span> <span>}); </span> $provide<span>.service('modalSvc', function(){ </span> <span>this.showModalDialog = jasmine.createSpy('showModalDialog'); </span> <span>}); </span> <span>}); </span> <span>module('services'); </span><span>}); </span> <span>beforeEach(inject(function($<span>window, modalSvc, sampleSvc</span>){ </span> mockWindow<span>=$window; </span> mockModalSvc<span>=modalSvc; </span> sampleSvcObj<span>=sampleSvc; </span><span>}));</span>
>如果存在標題和消息參數,請調用showmodalialog
- 以下片段顯示以下測試:
- 此方法沒有很多邏輯可以測試,而典型的Web應用程序中的服務通常會包含很多功能。您可以使用本提示中演示的技術來嘲笑和獲取對服務的參考。服務測試應涵蓋編寫服務時假定的所有可能場景。
>
測試控制器<span>it('should show alert when title is not passed into showDialog', function(){ </span> <span>var message="Some message"; </span> sampleSvcObj<span>.showDialog(message); </span> <span>expect(mockWindow.alert).toHaveBeenCalledWith(message); </span> <span>expect(mockModalSvc.showModalDialog).not.toHaveBeenCalled(); </span><span>}); </span> <span>it('should show modal when title is passed into showDialog', function(){ </span> <span>var message="Some message"; </span> <span>var title="Some title"; </span> sampleSvcObj<span>.showDialog(message, title); </span> <span>expect(mockModalSvc.showModalDialog).toHaveBeenCalledWith({ </span> <span>message: message, </span> <span>title: title </span> <span>}); </span> <span>expect(mockWindow.alert).not.toHaveBeenCalled(); </span><span>});</span>
測試控制器的設置過程與服務的設置過程完全不同。這是因為控制器不可注射,而是在路由加載或編譯NG控制器指令時自動實例化。由於我們沒有測試中的視圖加載,因此我們需要手動對正在測試的控制器進行實例化。
由於控制器通常與視圖相關,因此控制器中方法的行為取決於視圖。同樣,在彙編視圖後,可能會將一些其他對象添加到範圍中。其中最常見的示例之一是形式對象。為了使測試按預期工作,必須手動創建這些對象並將其添加到控制器中。
>
- >用於$ scope 的控制器 與控制器一起使用的控制器作為語法
>
>帶有$ scope的測試控制器
考慮以下控制器:為了測試此控制器,我們需要通過傳遞$ scope對象和一個模擬的服務對象(dataSVC)來創建控制器的實例。由於該服務包含異步方法,我們需要使用我在上一篇文章中概述的模擬承諾技術進行模擬。
angular<span>.module('services', []) </span> <span>.service('sampleSvc', ['$window', 'modalSvc', function($<span>window, modalSvc</span>){ </span> <span>this.showDialog = function(message<span>, title</span>){ </span> <span>if(title){ </span> modalSvc<span>.showModalDialog({ </span> <span>title: title, </span> <span>message: message </span> <span>}); </span> <span>} else { </span> $<span>window.alert(message); </span> <span>} </span> <span>}; </span> <span>}]);</span>
以下摘要模擬DataSvc服務:
當控制器向$範圍添加字段和方法時,我們可以檢查它們是否設置為正確的值,以及該方法是否具有正確的邏輯。上面的示例控制器添加了正則表達式以檢查有效的數字。 讓我們添加一個規格來測試正則表達式的行為:
<span>var mockWindow, mockModalSvc, sampleSvcObj; </span><span>beforeEach(function(){ </span> <span>module(function($provide){ </span> $provide<span>.service('$window', function(){ </span> <span>this.alert= jasmine.createSpy('alert'); </span> <span>}); </span> $provide<span>.service('modalSvc', function(){ </span> <span>this.showModalDialog = jasmine.createSpy('showModalDialog'); </span> <span>}); </span> <span>}); </span> <span>module('services'); </span><span>}); </span> <span>beforeEach(inject(function($<span>window, modalSvc, sampleSvc</span>){ </span> mockWindow<span>=$window; </span> mockModalSvc<span>=modalSvc; </span> sampleSvcObj<span>=sampleSvc; </span><span>}));</span>
如果控制器初始化具有默認值的任何對象,我們可以在規格中檢查其值。
<span>it('should show alert when title is not passed into showDialog', function(){ </span> <span>var message="Some message"; </span> sampleSvcObj<span>.showDialog(message); </span> <span>expect(mockWindow.alert).toHaveBeenCalledWith(message); </span> <span>expect(mockModalSvc.showModalDialog).not.toHaveBeenCalled(); </span><span>}); </span> <span>it('should show modal when title is passed into showDialog', function(){ </span> <span>var message="Some message"; </span> <span>var title="Some title"; </span> sampleSvcObj<span>.showDialog(message, title); </span> <span>expect(mockModalSvc.showModalDialog).toHaveBeenCalledWith({ </span> <span>message: message, </span> <span>title: title </span> <span>}); </span> <span>expect(mockWindow.alert).not.toHaveBeenCalled(); </span><span>});</span>
以下摘要測試此方法:
angular<span>.module('controllers',[]) </span> <span>.controller('FirstController', ['$scope','dataSvc', function($scope<span>, dataSvc</span>) { </span> $scope<span>.saveData = function () { </span> dataSvc<span>.save($scope.bookDetails).then(function (result) { </span> $scope<span>.bookDetails = {}; </span> $scope<span>.bookForm.$setPristine(); </span> <span>}); </span> <span>}; </span> $scope<span>.numberPattern = <span>/<span>^\d*$</span>/</span>; </span> <span>}]);</span>
>用“控制器”語法
測試控制器的測試控制器
>測試使用控制器作為語法的控制器比使用$範圍測試該控制器要容易得多。在這種情況下,控制器的實例扮演模型的角色。因此,所有操作和對像都可以在此實例上可用。>
考慮以下控制器:<span>module(function($provide){ </span> $provide<span>.factory('dataSvc', ['$q', function($q) </span> <span>function save(data){ </span> <span>if(passPromise){ </span> <span>return $q.when(); </span> <span>} else { </span> <span>return $q.reject(); </span> <span>} </span> <span>} </span> <span>return{ </span> <span>save: save </span> <span>}; </span> <span>}]); </span><span>});</span>
調用此控制器的過程與前面討論的過程相似。唯一的區別是,我們不需要創建$範圍。
>
>將控制器中的所有成員和方法添加到本實例中,我們可以使用實例參考訪問它們。
<span>beforeEach(inject(function($rootScope<span>, $controller, dataSvc</span>){ </span> scope<span>=$rootScope.$new(); </span> mockDataSvc<span>=dataSvc; </span> <span>spyOn(mockDataSvc,'save').andCallThrough(); </span> firstController <span>= $controller('FirstController', { </span> <span>$scope: scope, </span> <span>dataSvc: mockDataSvc </span> <span>}); </span><span>}));</span>
SAVEDATA方法的斷言保持不變。這種方法的唯一區別在於我們將值初始化為書籍尾尾和書形對象的方式。
<span>it('should have assigned right pattern to numberPattern', function(){ </span> <span>expect(scope.numberPattern).toBeDefined(); </span> <span>expect(scope.numberPattern.test("100")).toBe(true); </span> <span>expect(scope.numberPattern.test("100aa")).toBe(false); </span><span>});</span>
angular<span>.module('services', []) </span> <span>.service('sampleSvc', ['$window', 'modalSvc', function($<span>window, modalSvc</span>){ </span> <span>this.showDialog = function(message<span>, title</span>){ </span> <span>if(title){ </span> modalSvc<span>.showModalDialog({ </span> <span>title: title, </span> <span>message: message </span> <span>}); </span> <span>} else { </span> $<span>window.alert(message); </span> <span>} </span> <span>}; </span> <span>}]);</span>
>測試提供商
>提供商用於公開API,以進行全應用程序範圍的配置,該配置必須在應用程序啟動之前進行。一旦AngularJS應用程序的配置階段結束了,就不允許與提供商的交互。因此,只有在配置塊或其他提供商塊中訪問提供商。我們無法使用注入塊獲得提供商實例,而是需要將回調傳遞到模塊塊。
。>讓我們考慮以下依賴常數(AppConstants)第二提供商(另一個提供商)的提供商:
<span>var mockWindow, mockModalSvc, sampleSvcObj; </span><span>beforeEach(function(){ </span> <span>module(function($provide){ </span> $provide<span>.service('$window', function(){ </span> <span>this.alert= jasmine.createSpy('alert'); </span> <span>}); </span> $provide<span>.service('modalSvc', function(){ </span> <span>this.showModalDialog = jasmine.createSpy('showModalDialog'); </span> <span>}); </span> <span>}); </span> <span>module('services'); </span><span>}); </span> <span>beforeEach(inject(function($<span>window, modalSvc, sampleSvc</span>){ </span> mockWindow<span>=$window; </span> mockModalSvc<span>=modalSvc; </span> sampleSvcObj<span>=sampleSvc; </span><span>}));</span>
>
以下摘要獲取參考並加載模塊:>現在我們有所有參考文獻,我們可以調用提供商中定義的方法並測試:
<span>it('should show alert when title is not passed into showDialog', function(){ </span> <span>var message="Some message"; </span> sampleSvcObj<span>.showDialog(message); </span> <span>expect(mockWindow.alert).toHaveBeenCalledWith(message); </span> <span>expect(mockModalSvc.showModalDialog).not.toHaveBeenCalled(); </span><span>}); </span> <span>it('should show modal when title is passed into showDialog', function(){ </span> <span>var message="Some message"; </span> <span>var title="Some title"; </span> sampleSvcObj<span>.showDialog(message, title); </span> <span>expect(mockModalSvc.showModalDialog).toHaveBeenCalledWith({ </span> <span>message: message, </span> <span>title: title </span> <span>}); </span> <span>expect(mockWindow.alert).not.toHaveBeenCalled(); </span><span>});</span>
>單元測試有時會變得棘手,但是值得在其上花費時間,因為它可以確保應用程序的正確性。 AngularJS使使用框架編寫的代碼更加容易。我希望本文為您提供足夠的想法來擴展和增強應用程序中的測試。在以後的文章中,我們將繼續研究如何測試您的代碼的其他片段。
angular<span>.module('controllers',[]) </span> <span>.controller('FirstController', ['$scope','dataSvc', function($scope<span>, dataSvc</span>) { </span> $scope<span>.saveData = function () { </span> dataSvc<span>.save($scope.bookDetails).then(function (result) { </span> $scope<span>.bookDetails = {}; </span> $scope<span>.bookForm.$setPristine(); </span> <span>}); </span> <span>}; </span> $scope<span>.numberPattern = <span>/<span>^\d*$</span>/</span>; </span> <span>}]);</span>
在AngularJS中單位測試的重要性是什麼?它有助於隔離單個組件(例如服務,控制器和提供商)的功能。這樣可以確保每個組件在將它們集成到較大的應用程序中之前按預期工作。單元測試可以幫助識別開發過程的早期錯誤,從而使其更容易且成本更低。它還有助於維持代碼質量並提高應用程序的整體可靠性。>如何為AngularJS設置測試環境?首先,您需要安裝必要的測試工具,例如茉莉花和業力。 Jasmine是用於測試JavaScript代碼的行為驅動的開發框架,而Karma是在實際瀏覽器中執行測試的測試跑步者。安裝這些工具後,您可以在單獨的測試文件中編寫測試用例並使用業力運行。
如何測試AngularJS服務?
>>如何測試gangularjs控制器?
>測試AngularJS控制器涉及創建實例控制器並測試其方法和屬性。您可以使用AngularJS提供的$控制器服務創建控制器的實例。創建實例後,您可以調用其方法並檢查其對控制器範圍的影響。您還可以通過嘲笑服務並驗證其方法的調用來測試控制器與服務的互動。 >如何測試AngularJS提供商? >測試AngularJS提供商類似於測試服務。您可以將提供商注入測試,模擬其依賴項並測試其方法。但是,提供者有一種稱為“ $ get”的特殊方法,它返回服務實例。可以通過調用並檢查返回的值來分別測試此方法。 依賴項注入是AngularJS的關鍵功能,使您可以注入依賴性成分。在測試中,您可以使用此功能將依賴項的模擬版本注入正在測試的組件中。這使您可以隔離組件並獨立於其依賴項進行測試。 >
在單元測試angularJs組件中有哪些共同挑戰? >>單位測試AngularJS組件中的一些共同挑戰包括處理異步操作,測試指令以及處理外部依賴關係。異步操作可以使測試複雜且難以管理。由於與DOM的相互作用,測試指令可能很困難。外部依賴性(例如服務和API)可以使測試無法預測且難以隔離。 >>如何在AngularJS測試中處理異步操作?
>
>在AngularJS測試中的異步操作可以使用$ Q服務以及茉莉花提供的“完成”函數來處理。 $ Q服務使您可以創建可以在測試中解決或拒絕的承諾。可以調用“完成”功能以表示異步操作已經完成。 >
>如何測試AngularJS指令? >測試AngularJS指令涉及創建指令實例並測試其行為的實例。您可以使用AngularJS提供的$編譯服務創建指令實例。創建實例後,您可以使用類似jQuery的方法對其進行操作,並檢查其對范圍的影響。
>>我如何處理AngularJS測試中的外部依賴關係?可以通過嘲笑他們來處理。您可以創建依賴項的模擬版本,並將其註入正在測試的組件中。這使您可以控制依賴關係的行為,並隔離用於測試的組件。
>
>如何測試gangularjs控制器?
>測試AngularJS控制器涉及創建實例控制器並測試其方法和屬性。您可以使用AngularJS提供的$控制器服務創建控制器的實例。創建實例後,您可以調用其方法並檢查其對控制器範圍的影響。您還可以通過嘲笑服務並驗證其方法的調用來測試控制器與服務的互動。 >如何測試AngularJS提供商? >測試AngularJS提供商類似於測試服務。您可以將提供商注入測試,模擬其依賴項並測試其方法。但是,提供者有一種稱為“ $ get”的特殊方法,它返回服務實例。可以通過調用並檢查返回的值來分別測試此方法。>
在單元測試angularJs組件中有哪些共同挑戰? >>單位測試AngularJS組件中的一些共同挑戰包括處理異步操作,測試指令以及處理外部依賴關係。異步操作可以使測試複雜且難以管理。由於與DOM的相互作用,測試指令可能很困難。外部依賴性(例如服務和API)可以使測試無法預測且難以隔離。>>如何在AngularJS測試中處理異步操作?
>
>在AngularJS測試中的異步操作可以使用$ Q服務以及茉莉花提供的“完成”函數來處理。 $ Q服務使您可以創建可以在測試中解決或拒絕的承諾。可以調用“完成”功能以表示異步操作已經完成。>
>如何測試AngularJS指令?>測試AngularJS指令涉及創建指令實例並測試其行為的實例。您可以使用AngularJS提供的$編譯服務創建指令實例。創建實例後,您可以使用類似jQuery的方法對其進行操作,並檢查其對范圍的影響。
>>我如何處理AngularJS測試中的外部依賴關係?可以通過嘲笑他們來處理。您可以創建依賴項的模擬版本,並將其註入正在測試的組件中。這使您可以控制依賴關係的行為,並隔離用於測試的組件。
>以上是AngularJS中的單元測試:服務,控制器和提供商的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務
