AngularJS:如何编写控制器的单元测试

时间:2016-05-05 05:07:07

标签: javascript angularjs google-maps unit-testing jasmine

请原谅我如果我重复这个问题。 我对AngularJS和茉莉花的单元测试案例都很陌生。我最近开始玩angularJs。我已经阅读了很多文章,但我无法得到任何帮助。 我想为下面的控制器编写Jasmine单元测试用例。



intelApp.controller('healthIndexCtrl', [ '$scope','$http','$filter','deviceService', '$controller','$localStorage','getSensorDetails', function ($scope,$http,$filter,deviceService,$controller,$localStorage,getSensorDetails) {
	//device variable declaration
	$scope.device = {
			status : 'OFF',
			statusColor : 'red',
			id : '',
			parameterValues : [],
			trendChart : {
			currentChartData : ''
			}
		  };
	$scope.markers = [];
	$scope.devices=[];
	$scope.sensorData=[];
	$scope.isAnamolies='';
	$scope.pagination=true;
	$scope.tab2Show=false;
	//====================================Map functions==================================
	
	var mapOptions = {
	        zoom: 4,
	        center: new google.maps.LatLng(21.0000, 78.0000),
	        mapTypeId: google.maps.MapTypeId.TERRAIN
	    }
	    $scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
	   var infoWindow = new google.maps.InfoWindow();
	 
	var createMarker = function (info) {
	   
	   //set image depends on status
	   var markerIcon='';
	   if(info.status=='Green'){
			markerIcon='assets/images/green-dot.png';
	   }else if(info.status=='Yellow')
	   {
			markerIcon='assets/images/yellow-dot.png'
	   }
	   else{
		markerIcon='assets/images/red-dot.png';
	   }
	   
       var marker = new google.maps.Marker({
    	   	map: $scope.map,
            position: new google.maps.LatLng( info.latitude,  info.longitude),
			icon:markerIcon,
            title: info.city,
            Name:info.name
       	});
       
       google.maps.event.addListener(marker, 'mouseover', function () {
           infoWindow.setContent('<h4>Device Information</h4>Device Name : ' + marker.Name +'<br>DeviceType : ' +info.deviceType + '<br>Description : '+info.deviceDesc);
           infoWindow.open($scope.map, marker);
           $scope.information=true;
       });
	   
	   google.maps.event.addListener(marker, 'click', function () {
			$scope.trendchart(info.name);
	   });
	   
	    google.maps.event.addListener(marker, 'mouseout', function () {
			infoWindow.close();
	   });
            
       		$scope.markers.push(marker);
       		
    }
	
	$scope.openInfoWindow = function (e, selectedMarker) {
        e.preventDefault();
        google.maps.event.trigger(selectedMarker, 'click');
    }
		
	$scope.clearMarkers = function() {
	      for (var i = 0; i < $scope.markers.length; i++) {
	        $scope.markers[i].setMap(null);
	      }
	      $scope.markers.length = 0;
	    }
	$scope.zoomToIncludeMarkers = function() {
	    var bounds = new google.maps.LatLngBounds();
		console.log($scope.devices);
	      $scope.devices.forEach(function(device) {
        	 var latLng = new google.maps.LatLng(device.latitude,device.longitude);
        	 bounds.extend(latLng);
        });
           
          $scope.map.fitBounds(bounds);
     }
	
	  $("#mapCanvas").on('shown.bs.tab', function() {
		  $scope.tab2Show=false;
		  google.maps.event.trigger(map, 'resize');
		  $scope.zoomToIncludeMarkers();
		  $scope.$apply();
		  });
	  
	    $("#deviceList").on('shown.bs.tab', function() {
		  $scope.tab2Show=false;
		  $("#mytable tr").removeClass('selected');
		 $scope.$apply();
		  });
	  
	 //=============================Map ends here======================================
	

	/**
	 * $on function gives the filtered devices on healthindex page
	 */
	$scope.$on('passListToHealthIndex', function( event , obj){
		$scope.deviceListShow=true;
	    $scope.pagination=obj.devices.length>0?false:true;
	    $scope.tab2Show=false;
	    $scope.warningShow=false;
	    $scope.devices = obj.devices;
		console.log($scope.devices);
	    //Plot marker for maps
		  for(i=0;i<$scope.devices.length;i++){
			createMarker($scope.devices[i]);
			$scope.zoomToIncludeMarkers();
		 }
	    
	    //Pagination settings
	    $scope.viewby = 5;
		$scope.totalItems = $scope.devices.length;
		$scope.currentPage = 1;
		$scope.itemsPerPage = $scope.viewby;
		$scope.maxSize = 2; // Number of pager buttons to show		
		$scope.setPage = function (pageNo) {$scope.currentPage = pageNo;  };
		$scope.pageChanged = function() {
		 };
		  $scope.setItemsPerPage = function(num) {
			  $scope.itemsPerPage = num;
			  $scope.currentPage = 1; // reset to first paghe
		  }
	});
	
	
	//===============================Trend Chart ==============================
	//Function gets the sensor details, displays and visualize trend data in the line chart form 
	$scope.trendchart=function(deviceName){
		   for(var cnt=0;cnt<$scope.devices.id;cnt++){
			try{
			document.getElementById('trendChart'+cnt).innerHTML= '&nbsp;';
			}catch(e){
			}
		  }
			   $("#mytable tr").click(function(){
				   $(this).addClass('selected').siblings().removeClass('selected');    
				   var value=$(this).find('td:first').html();    
				 });

			   $('.ok').on('click', function(e){
				    alert($("#table tr.selected td:first").html());
				 });
				 
				 
			   
	/**
	 * @HTTP GET to get sensor details
	 * @param deviceName 
	 *@returns sensor details
	 */
		
		getSensorDetails.query({vending_machine_id:deviceName},function(RESPONSE){
			$scope.sensorData=RESPONSE.data;
			$scope.device.parameterValues = $scope.sensorData.sensors;
			
			$scope.tab2Show=$scope.device.parameterValues.length>0?true:false;
				
			var temp=$filter('filter')($scope.devices, {deviceId:deviceName})[0];
			$scope.isAnamolies=temp.status;
			
			if($scope.isAnamolies=='Yellow'){
				$scope.warningShow=true;
			}else{
				$scope.warningShow=false;
			}
			
			$scope.$apply();
			//Draw trendchart for each sensors
			for(var i=0;i<$scope.sensorData.sensors.length;i++){
				drawTrendChart($scope.sensorData.sensors[i],"#trendChart"+i,$scope,"Time",$scope.sensorData.sensors[i].details.sensorName);
				jQuery("#trendChart"+i).tooltip();
			}
		  		
					
		});
	 
	}
	 //Function to search device based on given searchString from devicelist
	 $scope.searchForDevice = function(arr, searchString){
		 if(!searchString){
			 return arr;
		 }	
		 var result = [];
		 searchString = searchString.toLowerCase();
		 angular.forEach(arr, function(item){
			 if(item.name.toLowerCase().indexOf(searchString) != -1){
				 result.push(item);
			 }	
		 });
		 return result;
	}
	 	//watches model "deviceSearchString" to get new values
	 $scope.$watch('deviceSearchString', function (newVal, oldVal) {
		 $scope.filteredDevices = $scope.searchForDevice($scope.devices, newVal);
		 $scope.totalItems = $scope.filteredDevices.length;
		 $scope.noOfPages = Math.ceil($scope.totalItems / $scope.itemsPerPage);
		 $scope.currentPage = 1;
		}, true);
		
	 //navigate to login page when you click on logout option in navigation
	 $scope.logout = function(){
		 window.location = "index.html"
		 }					
  
	
}]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
&#13;
&#13;
&#13;

此处&#34; getSensorDetails &#34;是工厂服务,它使用$ resouce进行REST服务。

&#13;
&#13;
intelApp.factory('getSensorDetails',function($resource){
	return $resource('http://retail-test-intelapiapp.demo-gotapaas.com/intel/sensorvalues',{},{
	//	return $resource('https://10.47.32.62:8244/deviceParameters/v1.0/sensorvalues',{},{
	query: {
        method: 'GET',
        transformResponse: function(data, headers){
            response = {};
			/*var temp=data.trim();
			temp=temp.substring(1,data.length-2);
			temp= temp.replace(/\\/g, "");*/
            response.data = JSON.parse(data);
            response.headers = headers();
            return response;
        }
	}});
});
&#13;
&#13;
&#13;

我知道如何为直接函数编写单元测试用例,但是这个控制器显示的不止于此。 如果有人能展示如何为控制器编写单元测试用例,那将是一件好事。

感谢Adavance 的问候,

1 个答案:

答案 0 :(得分:0)

请看一下这些,http://jasmine.github.io/edge/introduction.html http://ricostacruz.com/cheatsheets/jasmine.html 这个链接可以帮助您更好地理解。

很难解释,我会试一试。

测试应从描述开始,解释您要涵盖的内容,例如:

describe('healthIndexCtrl', function () {
});

然后在这个函数中你应该加载你的控制器和依赖文件,如

beforeEach(module('app.module.modulename')); // this is the module name of your controller.

现在控制器将开始运行。

然后,您需要将您在控制器中使用的依赖项注入到测试中,如下所示

var scope, http, filter, deviceService, controller, localStorage, getSensorDetails;
beforeEach(inject(function ($rootScope, $http, $filter, deviceService, $controller, $localStorage, getSensorDetails) {
    scope = $rootScope.$new();
    http = $http;
    deviceService = deviceService;
    controller = $controller;
    localStorage = $localStorage;
    getSensorDetails = getSensorDetails;
}));

注意:您只在注册文件中注入了依赖项,而不是在控制器中使用的所有依赖项。

然后,如果您正在进行后端或后端,或者您需要模拟工厂响应,则可以使用spyOn()伪造命中并给出如下所示的模拟响应。

spyOn(getSensorDetails,&#39; query&#39;)。and.returnValue(&#39;模拟你想要的响应。可以是任何数据类型,甚至是对象或数组&#39;);

然后最后你可以在it()中编写expect(),比如

it('some message', function () {
   scope.$digest();
   expect(scope.map).toBe('some mock');
});

我们正在使用范围。$ digest();这样控制器中的$ scope将使用规范中的模拟进行更新。

最后,总而言之,你的规范看起来像这样,

describe('healthIndexCtrl', function () {
    beforeEach(module('app.module.modulename'));

    var scope, http, filter, deviceService, controller, localStorage, getSensorDetails;
    beforeEach(inject(function ($rootScope, $http, $filter, deviceService, $controller, $localStorage, getSensorDetails) {
        scope = $rootScope.$new();
        http = $http;
        deviceService = deviceService;
        controller = $controller;
        localStorage = $localStorage;
        getSensorDetails = getSensorDetails;
     }));

     it('some message', function () {
        scope.$digest();
        expect(scope.map).toBe('some mock');
     });

});

希望这会有所帮助。