首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用angular-datatables时创建jasmine单元测试

如何在使用angular-datatables时创建jasmine单元测试
EN

Stack Overflow用户
提问于 2015-12-23 18:13:11
回答 2查看 1.6K关注 0票数 3

我在我的项目中使用了angular-datatables,我想为它写一个Jasmine/Karma单元测试。

这是我的控制器中的代码:

代码语言:javascript
复制
 $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响应呢?

EN

回答 2

Stack Overflow用户

发布于 2017-01-16 16:59:49

代码语言:javascript
复制
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操作并期望该方法已被调用将是安全的。

代码语言:javascript
复制
it('should have been called', function () {
  var spy = spyOn(DTOPtionsBuilder, 'fromSource');
  aliasOfYourController();
  expect(spy).toHaveBeenCalled();
});

如果您想要操作上述函数的返回值,我将获取sinonjs并将其设置为stub

代码语言:javascript
复制
it('became "foo"', function () {
  DTOptionsBuilder.fromSource = sinon.stub().returns('foo');
  aliasOfYourController();
  expect($scope.dtOptions).toEqual('foo');
});

现在,由于你使用的是promise,这有点复杂,但是生成一个基于promise的函数的基础是:

  • $q注入到您的规范文件中。
  • 告诉stub在promise.
  • Run解析为的情况下返回
  • ,在rejected promise.
  • Run $timeout.flush()的情况下返回$q.reject(/** err **/),以刷新所有延迟任务。如果您模拟的是http响应,那么您可以在单元测试中使用$httpBackend,并在done回调中使用$httpBackend.flush()刷新所有延迟的done回调,通知Jasmine您已经完成了异步任务的等待(可能不需要)。这取决于测试框架/运行器。

它可能看起来像这样:

代码语言:javascript
复制
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'),那么单元测试用例可以是:

代码语言:javascript
复制
   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和存根的想法。

票数 1
EN

Stack Overflow用户

发布于 2015-12-23 18:29:46

要模拟http响应,可以在单元测试中使用$httpBackend。

如果您希望在未发出请求的情况下测试失败,请使用$httpBackend.expect。你也可以定义一个模拟响应。

如果您希望在发出请求但不强制请求的情况下定义模拟响应,请使用$httpBackend.when。

用于解释的代码...

要测试的控制器代码

代码语言:javascript
复制
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");
    });
}

单元测试代码...

代码语言:javascript
复制
$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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34433286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档