使用 jasmine 对控制器中基于资源的工厂进行角度 js 单元测试

     2023-02-23     252

关键词:

【中文标题】使用 jasmine 对控制器中基于资源的工厂进行角度 js 单元测试【英文标题】:angular js unit test using jasmine for a resource based factory in controller 【发布时间】:2016-07-27 18:31:12 【问题描述】:

我是使用 jasmine 编写单元测试用例的新手。我正在尝试在控制器中测试基于资源的服务,该控制器从服务器获取真实数据但没有得到预期的结果。请在我做错的地方提供您的意见。下面是我写的单元测试: 描述('NewStarterController',函数() beforeEach(module('myApp')); var 范围,ctrl,$resource;

       var context = 'http://localhost.com:8085/AngularPrototype/home';

       beforeEach(inject(function(_$resource_, $rootScope, $controller) 
              $resource = _$resource_;

              NewStarter = 
                     getNSData : function() 
                           return $resource(context + '/selfservice/newstarter/get', , 
                                  get : 
                                         method : 'GET'
                                  
                           );
                     
              ;
              scope = $rootScope.$new();

              $controller('NewStarterController', 
                     $scope : scope,
                     NewStarter : NewStarter
              );

       ));

       it('should test new starter data', function() 

              NewStarter.getNSData().get().$promise.then(function(response) 
                     scope.refData = response;
                     scope.data();

              );


              expect(scope.data.length).toEqual(2);

              expect(NewStarter.getNSData().get.length).toEqual(2);

              expect(NewStarter.getNSData().get()).toEqual('formTitleNode');

       );

); 



Below is the jasmine test result ::

Jasmine 1.3.1 revision 1354556913finished in 0.183s
•   
No try/catchFailing 1 spec1 spec | 1 failing
NewStarterController
should test new starter data
NewStarterController should test new starter data.
Expected 0 to equal 2.
Expected 4 to equal 2.
Expected  $promise :  $$state :  status : 0  , $resolved : false  to equal 'formTitleNode'.





get.json      ->   represents the data that is returned from server(Data returned from RestController) on hitting the url : http://localhost.com:8085/AngularPrototype/home/selfservice/newstarter/get

SpecRunner.html->  is used to run the jasmine unit test. Below are the contents of this file :
<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Jasmine Demo</title>

    <script>
        libraries here
    </script>
</head>
<body>
<!-- Include Angular and Angular Mocks-->
<script>libraries here </script>
    <!-- Include your source files here... -->
<script src="services/services.js"></script>
<script src="myApp.js"></script>
<script src="controller/selfservice/NewStarterController.js"></script>

<!-- Include your spec files here... -->
<script src="jasmineunittest/NewStarterControllerTest.js"></script>


<!-- Jasmine execution script (Standard Jasmine Bolierplate)-->
<script type="text/javascript">
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();

</script>

</body>
</html> 


Below is the controller code ( NewStarterController.js ) which is unit tested : 

myApp.controller("NewStarterController", ['$scope','$modal', '$state', '$sce', 'NewStarter', function($scope,$modal, $state, $sce, NewStarter) 


       $scope.data = function() 
              NewStarter.getNSData().get(, function(response) 
                     $scope.refData = response;
                     $scope.formTitle = [];
                     $scope.displayOptions = [];
                     angular.forEach($scope.refData.formTitleNode, function(contentItem)
                     
                           var content = -1;
                           var title = -1;
                           angular.forEach(contentItem.fieldList, function(fieldBean)
                           
                                  if(fieldBean.fieldName == 'TITLE')
                                  
                                         title = fieldBean.fieldValue;

                                  
                                  if(fieldBean.fieldName == 'FORMATTEDCONTENTS')
                                  
                                         content = fieldBean.fieldValue;

                                  
                           )
                           $scope.formTitle.push(title:title, content:content);
                     )

                     angular.forEach($scope.refData.displayOptionsNode, function(contentItem)
                     

                           var nsContent = -1;
                           var nsTitle = -1;
                           angular.forEach(contentItem.fieldList, function(fieldBean)
                           
                                  if(fieldBean.fieldName == 'TITLE')
                                  
                                         nsTitle = fieldBean.fieldValue;

                                  
                                  if(fieldBean.fieldName == 'FORMATTEDCONTENTS')
                                  
                                         nsContent = fieldBean.fieldValue;

                                  
                           )
                           $scope.displayOptions.push(nsTitle:nsTitle, nsContent:nsContent);
                           $scope.selectedOption = '';
                     )

                     $scope.hasNewStarterSubmitted = $scope.refData.hasNewStarterSubmitted;
                     $scope.submittedSelectedOption = $scope.refData.submittedSelectedOption;
                     $scope.submittedStudentLoan = $scope.refData.submittedStudentLoan;
                     $scope.nsAlreadySubmittedValidationMsg = $scope.refData.nsAlreadySubmittedValidationMsg;



                     console.log('Success', response);
              , function(error) 
                     //alert(JSON.stringfy(error))
                     $scope.contentLoadErrorMsg=error.data;
                     //console.error('ERR', error);
              );
       
]);





Below is the code in services.js

myApp.factory('NewStarter', function($resource, context) 
       return 
              getNSData: function() 
                     return $resource(context + '/selfservice/newstarter/get', , get: method:'GET');
              ,
              submitNSForm: function() 
                     return $resource(context + '/selfservice/newstarter/submit', , submit: method:'POST');
              

       
);


Below is the code in myApp.js 

var myApp = angular.module('myApp', ['ngResource', 'ngSanitize', 'ui.bootstrap', 'ui.router']);

myApp.constant('context', '/AngularPrototype/home');
myApp.constant('projectName', '/AngularPrototype');
myApp.config(function($stateProvider, $urlRouterProvider, projectName) 
$urlRouterProvider.otherwise('/home');

$stateProvider .state('newStarter', 
                     url:'/newstarter',
                     templateUrl: projectName + '/newstarter',
                     controller: 'NewStarterController'
              )
);


 Thanks!  



Below i tried as per your suggestion but getting error while running the unit test:
describe('NewStarterController', function()  
beforeEach(module('myApp')); 
var scope, postDefer,NewStarter;



       beforeEach(inject(function(_NewStarter_, $rootScope, $controller,$q) 
              NewStarter = _NewStarter_;
             postDefer = $q.defer();
             spyOn(NewStarter,'getNSData').and.returnValue(postDefer.promise);
              scope = $rootScope.$new();

              $controller('NewStarterController', 
                     $scope : scope,
                     NewStarter : NewStarter
              );

       ));

       it('should test new starter data', function() 

              NewStarter.getNSData().get();
              postDefer.resolve();
              scope.$apply();

              expect(scope.data.length).toEqual(2);

       );

); 


Below are the errors while running the test :

Error:[$injector:unpr] Unknown provider: NewStarterProvider <- NewStarter
typeError: Unable to get property 'getNSData' of undefined or null reference

【问题讨论】:

您的模拟 getNSData 不必调用 $resource,只需返回一个承诺,并在需要验证结果时解决该承诺。检查我对其他问题的回答***.com/questions/36189329/… 我按照您的建议进行了尝试,但没有成功。无法识别 getNSData 方法。可以分享一下代码吗??谢谢! 您能否根据我的建议使用您尝试过的代码更新您的问题? 用我尝试过的代码更新了问题,并提到了我在运行单元测试时遇到的错误。请查看并提供您的宝贵意见。谢谢! 【参考方案1】:

由于是单元测试,需要重点测试单个单元,尽量mock所有依赖。话虽如此,在单元测试中使用真正的 $resource 是不可取的。

我认为你应该做的是:- 1. 模拟 NewStarter.getNSData(),或在控制器中调用的任何服务方法 2.返回一个伪造的资源对象 3. 模拟假资源的 get 方法(因为它是在你的控制器中使用的)并返回一个承诺 4. 兑现承诺以测试您的成功处理程序。

看看这个笨蛋http://plnkr.co/edit/8l3mY1?p=preview

var  mockResource = get: function(), $q;
beforeEach(inject(function($rootScope, $controller, _$q_, NewStarter) 
  $scope = $rootScope.$new();
  $q = _$q_;
  spyOn(NewStarter, 'getNSData').and.callFake(function() 
     return mockResource;
  );

  ctrl = $controller('MainCtrl', 
    $scope: $scope
  );
));

it('should return value', function() 
  var responseObj = id: 1, name:'test';
  spyOn(mockResource, 'get').and.callFake(function(data, func)
      var deferred = $q.defer();
      deferred.resolve(responseObj);
      return deferred.promise.then(func);
    );

  $scope.data();

  expect(mockResource.get).toHaveBeenCalled();  
  $scope.$apply();

  expect($scope.refData).toEqual(responseObj);
);

【讨论】:

如何在 Jasmine 单元测试中使用 Sinon 对 jQuery 动画进行假时间?

】如何在Jasmine单元测试中使用Sinon对jQuery动画进行假时间?【英文标题】:HowdoIfake-timeajQueryanimationusingSinoninaJasmineunittest?【发布时间】:2011-11-1113:10:27【问题描述】:我有一个1秒的jQuery.animate操作,在页面加载后5秒启动。我在Ja... 查看详情

如何对 AngularJS $promise.then 进行单元测试

...ces的函数,并使用工厂来查询我的所有数据。然后在我的控制器中,我使用该服务和$promise.then来获取我的数据并将其存储在一 查看详情

在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试

】在Angular中使用Jasmine使用*ngIf指令时,如何对元素是不是可见进行单元测试【英文标题】:HowdoIunittestifanelementisvisiblewhenthe*ngIfdirectiveisusedusingJasmineinAngular在Angular中使用Jasmine使用*ngIf指令时,如何对元素是否可见进行单元测试【... 查看详情

使用 Jasmine 监视私有变量的属性/函数

】使用Jasmine监视私有变量的属性/函数【英文标题】:Spyonanattribute/functionofaprivatevariablewithJasmine【发布时间】:2020-07-1603:21:02【问题描述】:我有一个基于它读取的文件具有可变功能的函数,该函数通过它保存在内存中的Map进行... 查看详情

在 Jasmine 单元测试中模拟 AngularJS 模块依赖项

...】:2013-07-0710:38:36【问题描述】:我试图在一个模块中对控制器代码进行单元测试,该模块将其他模块作为依赖项,但无法弄清楚如何正确模拟它们。我正在使用Jasmine框架并使用Karma(Testacular)运行我的测试。模块代码var 查看详情

使用 Jasmine 进行异步测试

】使用Jasmine进行异步测试【英文标题】:AsynctestwithJasmine【发布时间】:2013-06-2802:33:07【问题描述】:我正在尝试对Jasmine和RequireJS进行一些测试。一切都很顺利,直到我注意到我所描述的函数的上下文存在问题。我正在做一些Aj... 查看详情

为啥使用 jasmine 对 Node typescript 项目进行 Karma 单元测试会显示包含依赖项的覆盖范围?

】为啥使用jasmine对Nodetypescript项目进行Karma单元测试会显示包含依赖项的覆盖范围?【英文标题】:WhyKarmaunittestswithjasmineforaNodetypescriptprojectshowscoverageincludingadependency?为什么使用jasmine对Nodetypescript项目进行Karma单元测试会显示包... 查看详情

透过现象看本质——聊一聊docker的硬件资源控制与验证(代码片段)

...机制——Controlgroup?Controlgroup是Linux内核提供的一种限制所使用物理资源的机制,这些资源主要是CPU、内存、blkio,而Controlgroup简称为Cgroup,我们可以在下面的目录中查看:[root@dockercgroup]#lsblkiocpuacctcpusetfreezermemorynet_cls,net_prioperf_ev... 查看详情

使用 postMessage 和 addEventListener 进行 Jasmine 单元测试

】使用postMessage和addEventListener进行Jasmine单元测试【英文标题】:JasmineUnitTestwithpostMessageandaddEventListener【发布时间】:2015-09-1223:33:04【问题描述】:我正在尝试使用postMessage和addEventListener对情况进行单元测试。用例是我使用类似... 查看详情

Jasmine 使用 Angular 中的 TypeScript 对文件大小进行单元测试

】Jasmine使用Angular中的TypeScript对文件大小进行单元测试【英文标题】:JasmineunittestforfilesizewithTypeScriptinAngular【发布时间】:2019-01-1513:27:13【问题描述】:寻找最佳实践如何在inputtype="file"更改事件上测试文件大小。现在我的测试... 查看详情

无法使用 Spring Webflux 和 Thymeleaf 对静态资源进行版本控制

】无法使用SpringWebflux和Thymeleaf对静态资源进行版本控制【英文标题】:NotabletoversionstaticresourceswithSpringWebfluxandThymeleaf【发布时间】:2019-05-1600:01:18【问题描述】:我尝试使用SpringWebflux在我的应用程序上实现静态内容版本控制,... 查看详情

使用 OpenId Connect 进行基于声明的身份验证

...P.NETCore。不执行任何策略的授权按预期工作。我想对某些控制器和操作方法强制执行授权策略。我所有的用户都有角色声明,所以我在Startup 查看详情

基于sdn的访问控制模块实现(代码片段)

...行未授权的访问,从而使计算机系统在合法的范围内使用。意指用户身份及其所归属的某项定义组来限制用户对某些信息项的访问,或限制对某些控制功能的使用的一种技术。访问控制通常是系统管理员控制用户对服务... 查看详情

基于sdn的访问控制模块实现(代码片段)

...行未授权的访问,从而使计算机系统在合法的范围内使用。意指用户身份及其所归属的某项定义组来限制用户对某些信息项的访问,或限制对某些控制功能的使用的一种技术。访问控制通常是系统管理员控制用户对服务... 查看详情

使用 Karma Jasmine 的 Angular 1.5 组件模板单元测试

...ar组件和模板进行单元测试。我正在使用ng-html2js测试组件控制器已实现但不是模板我引用thisGitRepository作为其中的一部 查看详情

labview中使用gpu进行高性能计算

项目中需要使用LabVIEW控制NIFPGAboard产生控制信号等,使用GPU对采集的数据进行高性能计算,因此方案之一是用VisualStudio设计基于CUDA的GPU并行计算算法代码,然后生成DLL,使用LabVIEW设计NIFPGAboard控制代码并调用DLL,采用LabVIEW完成... 查看详情

基于角色与基于资源的权限访问控制

  基于角色的权限访问控制RBAC(role-basedaccesscontrol)是以角色为中心进行的访问控制,也就是判断主体subject是那个角色的方式进行权限访问控制,是粗粒度的  基于资源的权限访问控制RBAC(resource-basedaccesscontrol)是以资源... 查看详情

权限框架基础知识

...些资源没有权限是无法访问的 3.权限控制  1)基于角色    RBAC基于角色的访问控制(Role-BasedAccessControl)是以角色为中心进行访问控制,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资... 查看详情