我在我的项目中使用了angular-datatables,我想为它写一个Jasmine/Karma单元测试。
这是我的控制器中的代码:
$scope.dtOptions = DTOptionsBuilder.fromSource('/api/books/')
.withBootstrap()
.withPaginationType('simple_numbers')
.withDisplayLength(10)
//.withOption('serverSide', true)
.withOption('processing', true)
.withOption('createdRow', createdRow);
$scope.dtColumns = [
DTColumnBuilder.newColumn('id').withTitle('ID'),
DTColumnBuilder.newColumn('name').withTitle('Name')
DTColumnBuilder.newColumn(null).withTitle('Actions').notSortable()
.renderWith(actionsHtml)
];我现在如何为它编写一个单元测试,从/api/books伪造一个JSON响应呢?
发布于 2017-01-16 16:59:49
var $scope, $state, DTColumnBuilder, DTOptionsBuilder, createController, $httpBackend;
beforeEach(function () {
DTColumnBuilder = {};
DTOptionsBuilder = {};
$state = {};
$httpBackend = {};
module('app', function ($provide) {
$provide.value('$state', $state);
$provide.value('$httpBackend', $httpBackend);
$provide.value('DTColumnBuilder', DTColumnBuilder);
$provide.value('DTOptionsBuilder', DTOptionsBuilder);
});
inject(function ($controller, $injector) {
$scope = $injector.get('$rootScope').$new();
$state = $injector.get('$state');
$httpBackend = $injector.get('$httpBackend');
DTColumnBuilder = $injector.get('DTColumnBuilder');
DTOptionsBuilder = $injector.get('DTOptionsBuilder');
aliasOfYourController = function () {
return $controller('originalNameOfController', {
$scope: scope,
$state: $state,
DTOptionsBuilder: DTOptionsBuilder,
DTColumnBuilder: DTColumnBuilder
});
}
spyOn($state, 'go');
$httpBackend.flush();
});
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
// Stub out the methods of interest.
DTOptionsBuilder.fromSource = angular.noop;
DTColumnBuilder.bar = function () { return 'bar'; };
});spy的本质是让原始实现完成它的事情,但记录对该函数的所有调用以及相关数据的分类。
另一方面,stub是具有扩展spy的API,您可以在其中完全修改所述函数的工作方式。返回值、预期参数等。
假设我们使用了前面提到的beforeEach块,此时DTOptionsBuilder.fromSource将是一个noop。因此,对其执行spy操作并期望该方法已被调用将是安全的。
it('should have been called', function () {
var spy = spyOn(DTOPtionsBuilder, 'fromSource');
aliasOfYourController();
expect(spy).toHaveBeenCalled();
});如果您想要操作上述函数的返回值,我将获取sinonjs并将其设置为stub。
it('became "foo"', function () {
DTOptionsBuilder.fromSource = sinon.stub().returns('foo');
aliasOfYourController();
expect($scope.dtOptions).toEqual('foo');
});现在,由于你使用的是promise,这有点复杂,但是生成一个基于promise的函数的基础是:
$q注入到您的规范文件中。stub在promise.$timeout.flush()的情况下返回$q.reject(/** err **/),以刷新所有延迟任务。如果您模拟的是http响应,那么您可以在单元测试中使用$httpBackend,并在done回调中使用$httpBackend.flush()刷新所有延迟的done回调,通知Jasmine您已经完成了异步任务的等待(可能不需要)。这取决于测试框架/运行器。它可能看起来像这样:
it('resolves with "foo"', function (done) {
DTOptionsBuilder.fromSource = sinon.stub().returns($q.when('foo'));
expect($scope.options).to.eventually.become('foo').and.notify(done); // this is taken from the chai-as-promised library, I'm not sure what the Jasmine equivalent would be (if there is one).
aliasOfYourController();
$timeout.flush();
});而且,如果您想测试$state.go('toSomeState'),那么单元测试用例可以是:
it('should redirected successfully', function() {
var stateParams = {
id: 22,
name: sample
}
functionNameInsideWhichItsBeenCalled(stateParams);
expect($state.go).toHaveBeenCalledWith('toSomeState', {
id: stateParams.id,
name: stateParams.name
});
});现在,在这一点上,很多都只是猜测。如果不让源代码在我旁边运行以供交叉引用,就很难建立一个完全工作的测试套件,但我希望这至少能给你一些关于如何使用$httpBackend、spy和存根的想法。
发布于 2015-12-23 18:29:46
要模拟http响应,可以在单元测试中使用$httpBackend。
如果您希望在未发出请求的情况下测试失败,请使用$httpBackend.expect。你也可以定义一个模拟响应。
如果您希望在发出请求但不强制请求的情况下定义模拟响应,请使用$httpBackend.when。
用于解释的代码...
要测试的控制器代码
self.callme = function() {
$http.get('/mypath').then(function() {
console.log("I will be executed when flush is called if the mock API response is 2xx");
}).catch(function() {
console.log("I will be executed when flush is called if the mock API response is NOT 2xx");
});
}单元测试代码...
$httpBackend.expectGET('/mypath').respond(200, {data:"fred"});
controller.callme();
// The THEN code has not been executed here
$httpBackend.flush();
// The THEN success code is now executed because we responded with 2xx (200)https://stackoverflow.com/questions/34433286
复制相似问题