Angular/Mocha/Chai - 为单元测试初始化控制器?
Angular/Mocha/Chai - initialize controller for unit testing?
我们刚刚开始在 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 服务 运行 以及如何处理最终的 return 数据并不明显。我们已经尝试了 $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?
});
});
通常最好分别测试服务和控制器。
要测试服务,您可以使用 $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_;
}));
如果你需要API代理return一个承诺,你也可以模拟它
https://docs.angularjs.org/api/ng/service/$q
并解决,例如:
var deferred = $q.defer();
deferred.resolve({'mocked':'data'});
return deferred.promise;
如果你确实想一起测试它们,你可以对你调用的 API 函数进行监视,并让监视 return 一个已解决的承诺。
我们刚刚开始在 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 服务 运行 以及如何处理最终的 return 数据并不明显。我们已经尝试了 $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?
});
});
通常最好分别测试服务和控制器。
要测试服务,您可以使用 $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_;
}));
如果你需要API代理return一个承诺,你也可以模拟它 https://docs.angularjs.org/api/ng/service/$q 并解决,例如:
var deferred = $q.defer();
deferred.resolve({'mocked':'data'});
return deferred.promise;
如果你确实想一起测试它们,你可以对你调用的 API 函数进行监视,并让监视 return 一个已解决的承诺。