服务可以取决于一组其他服务来执行其任务。说,名为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
>
测试控制器<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对象和一个模拟的服务对象(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服务?
>如何测试gangularjs控制器?
>测试AngularJS控制器涉及创建实例控制器并测试其方法和属性。您可以使用AngularJS提供的$控制器服务创建控制器的实例。创建实例后,您可以调用其方法并检查其对控制器范围的影响。您还可以通过嘲笑服务并验证其方法的调用来测试控制器与服务的互动。>如何测试AngularJS提供商?>测试AngularJS提供商类似于测试服务。您可以将提供商注入测试,模拟其依赖项并测试其方法。但是,提供者有一种称为“ $ get”的特殊方法,它返回服务实例。可以通过调用并检查返回的值来分别测试此方法。>
在单元测试angularJs组件中有哪些共同挑战?>>单位测试AngularJS组件中的一些共同挑战包括处理异步操作,测试指令以及处理外部依赖关系。异步操作可以使测试复杂且难以管理。由于与DOM的相互作用,测试指令可能很困难。外部依赖性(例如服务和API)可以使测试无法预测且难以隔离。>
>在AngularJS测试中的异步操作可以使用$ Q服务以及茉莉花提供的“完成”函数来处理。 $ Q服务使您可以创建可以在测试中解决或拒绝的承诺。可以调用“完成”函数以表明异步操作已经完成。>
>测试AngularJS指令涉及创建指令实例并测试其行为的实例。您可以使用AngularJS提供的$编译服务创建指令实例。创建实例后,您可以使用类似jQuery的方法对其进行操作,并检查其对范围的影响。>
以上是AngularJS中的单元测试:服务,控制器和提供商的详细内容。更多信息请关注PHP中文网其他相关文章!