我们刚开始使用Angular应用程序中的单元测试,我们正在使用karma / mocha / chai框架进行单元测试。我对我们定义的各种服务和工厂进行了一些基本的单元测试,单元测试工作得很好。但是现在我们要测试一些控制器并评估控制器正在修改的范围变量。
这是一个这样的控制器的例子:
angular.module('App').controller('myCtrl', ['$scope', 'APIProxy',
function ($scope, APIProxy) {
$scope.caseCounts = {caseCount1: 0, caseCount2: 0};
$scope.applyCounts = function () {
$scope.caseCounts.caseCount1 = {...some case count logic...}
$scope.caseCounts.caseCount2 = {...some case count logic...}
};
APIProxy.getAll().then(function (data) {
{...do a bunch of stuff...}
$scope.data = data;
$scope.applyCounts();
});
}]
);
现在,当我进行单元测试时,我想从一个简单的'开始'$ scope.caseCounts具有值> 0,然后我将从那里建造。但是,如何使控制器导致APIProxy服务运行以及如何处理最终的数据返回并不明显。我们已经尝试了$ scope.getStatus()和$ scope.apply()以及其他一些东西,但我觉得我们已经偏离了标准,我们从根本上错过了一些关于如何解决这个问题的事情。
目前我们的控制器测试仪看起来像:
describe("myCtrl unit tests",function(){
beforeEach(module('App'));
var ctrl, APIProxy;
beforeEach(inject(function ($rootScope, $controller, _APIProxy_)
{
$scope = $rootScope.$new();
APIProxy = _APIProxy_;
ctrl = $controller('myCtrl', {$scope: $scope, APIProxy: APIProxy});
}));
it('Loads data correctly', function() {
expect(ctrl).to.not.be.undefined;
//??? what else do we do here to fire the getAll function in controller?
});
});
答案 0 :(得分:2)
分别测试服务和控制器通常会更好。
要测试服务,您可以使用$ httpBackend来模拟XHR请求:
https://docs.angularjs.org/api/ngMock/service/$httpBackend
要测试控制器,您可以在初始化控制器时提供模拟值而不是实际服务
APIProxy = {'mocked':'data'};
ctrl = $controller('myCtrl', {$scope: $scope, APIProxy: APIProxy});
或者更一般地说,模拟模块的任何提供者:
module(function($provide) {
$provide.constant('ab','cd');
$provide.value('ef', 'gh');
$provide.service('myService', function() { });
});
这会覆盖' myService'在控制器中引用为依赖项(如果有的话)。如果你需要它,你也可以注入它:
var myService;
beforeEach(inject(function (_myService_) {
myService = _myService_;
}));
如果您需要APIProxy返回承诺,您也可以使用它来模拟它 https://docs.angularjs.org/api/ng/service/$q 并解决,例如:
var deferred = $q.defer();
deferred.resolve({'mocked':'data'});
return deferred.promise;
如果您确实想要一起测试它们,您可以对您调用的API函数进行间谍,并让间谍返回已解决的承诺。