2016-08-25 65 views
0

有人可以告诉我在我的控制器函数getData和工厂函数上运行测试的最佳方法。我很困惑,不知道从哪里开始。你会如何为下面的代码编写测试?Karma测试控制器,用http调用服务

myApp.controller('myController', ['$scope', 'myFactory', function ($scope, myFactory) { 

    $scope.getData = function(id) { 
     var promise = myFactory.GetData('/dta/GetData?Id=' + id); 
     promise 
     .then(function (success) { 
      $scope.result = success; 
     }, function (error) { 
      $scope.error = true; 
     }); 
    } 
}); 


myApp.factory('myFactory', ['$http', function ($http) { 
    return { 
     GetData: function (url) { 
      return $http.get(url) 
      .then(function (response) { 
       return response.data; 
      }, function (error) { 
       return error; 
      }); 
     } 
    } 
}]); 
+0

那你想测试,你的控制器的'getData'方法或你更有用工厂的GetData方法? – Phil

+0

...对于前者,你会[myFactory] ​​[创建一个模拟(间谍)](http://jasmine.github.io/2.0/introduction.html#section-Spies:_ createSpyObj)。对于后者,使用['$ httpBackend'](https://docs.angularjs.org/api/ngMock/service/$httpBackend) – Phil

+0

我想测试上面看到的所有代码。我不确定有经验的测试人员会做什么。 – user1024941

回答

1

你会想孤立地测试每个组件(这就是单元测试的目的)。因此,像这样的控制器

describe('myController test',() => { 
    let scope, myFactory; 

    beforeEach(() => { 
     myFactory = jasmine.createSpyObj('myFactory', ['GetData']);    

     module('your-module-name'); 
     inject(function($rootScope, $controller) { 
      scope = $rootScope.$new(); 

      $controller('myController', { 
       $scope: scope, 
       myFactory: myfactory 
      }); 
     }); 
    }); 

    it('getData assigns result on success', inject(function($q) { 
     let id = 1, success = 'success'; 
     myFactory.GetData.and.returnValue($q.when(success)); 

     scope.getData(id); 
     expect(myFactory.GetData).toHaveBeenCalledWith('/dta/GetData?Id=' + id); 
     scope.$digest(); // resolve promises 
     expect(scope.result).toBe(success); 
    })); 

    it('getData assigns error on rejections', inject(function($q) { 
     myFactory.GetData.and.returnValue($q.reject('error')); 

     scope.getData('whatever'); 
     scope.$digest(); 
     expect(scope.error).toEqual(true); 
    })); 
}); 

对于你的工厂,你会创建一个单独的describe并注入和配置$httpBackend。文档中有很多例子。


仅供参考,您应该忽略的错误处理程序在你的工厂,即

return $http.get(url).then(response => response.data); 

,或者如果你不喜欢ES2015

return $http.get(url).then(function(response) { 
    return response.data; 
}); 

,你正在把失败的请求成为一个成功的承诺。


事实上,我会走得更远一点,让您的GetData工厂不仅仅是一个$http包装

GetData: function(id) { 
    return $http.get('/dta/GetData', { 
     params: { Id: id } 
    }).then(function(res) { 
     return res.data; 
    }); 
} 
+0

我已经修改我的工厂为GetData:function(url){return $ http.get(url);}但是现在预计(scope.result).toBe(success);不起作用。我不确定现在应该是什么。 – user1024941

+0

@ user1024941您似乎错过了使用'response.data'解决的部分。这应该不会改变你的测试 – Phil

+0

为什么我需要服务中的then子句,什么时候可以将它放在我的控制器中并访问success.data? – user1024941