簡體   English   中英

功能單元測試

[英]Unit testing for function

我正在為功能getNextPage()編寫單元測試。 我設置了測試:Expect(this.anotherService.resources).toEqual(3); 我收到錯誤消息:運行測試時,預期undefined等於3。 我記錄了anotherService.resources,它在控制台中返回了3。 不知道為什么它不起作用。

測試

describe('Test for someController', function() {
  beforeEach(function() {
    module('someApp');
    return inject(function($injector) {
      var $controller;
      var $q = $injector.get('$q');

      this.rootScope = $injector.get('$rootScope');
      $controller = $injector.get('$controller');
      this.state = $injector.get('$state');
      this.stateParams = {
        id: 1,
      }
      this.location = $injector.get('$location')
      this.timeout = $injector.get('$timeout')
      this.upload = $injector.get('$upload')
      this.someService = {
        getItemList: function(res) {
          var deferred = $q.defer();
          deferred.resolve({
            data: {
              totalRows: 2,
              rows: 3,
            }
          });
          return deferred.promise;
        },
        pages: jasmine.createSpy(),

        memberIds: 1,
        currEng: []
      };
      this.anotherService = {
        resources: {}
      };
      this.scope = this.rootScope.$new();
      this.controller = $controller('someController', {
        '$scope': this.scope,
        '$rootScope': this.rootScope,
        '$state': this.state,
        '$stateParams': this.stateParams,
        '$location': this.location,
        '$timeout': this.timeout,
        '$upload': this.upload,
        'someService': this.someService,
      });
      this.scope.$digest();
    });
  });

  it('should be defined', function() {
    expect(this.controller).toBeDefined();
    expect(this.scope.ss).toEqual(this.someService);
  });

  it('should run the getNextPage function', function() {
    this.scope.getNextPage();
    this.scope.$digest();
    console.log(this.anotherService.resources);        // this is showing as Object {} in terminal
    expect(this.anotherService.resources).toEqual(3);
  });

碼:

someapp.controller('someController', resource);
resource.$inject = ['$scope', '$state', '$stateParams', '$location','$timeout','$upload', 'someService', 'anotherService'];
function resource($scope, $state, $stateParams,$location,$timeout, $upload, someService, anotherService) {

      $scope.fileReaderSupported = window.FileReader != null && (window.FileAPI == null || FileAPI.html5 != false);

      $scope.ss = EsomeService;
      $scope.as = anotherService;
      $scope.getNextPage = getNextPage;


      function getNextPage(options){

        var o = options || {selected:1};
        var start = (o.selected-1)*10 || 0;
        someService.currPage = o.selected;

        someService.getItemList($stateParams.id,'F', start).then(function (res){
          anotherService.resources = res.data.rows;
          console.log(anotherService.resources)   // this shows LOG: 3 in terminal
          someService.numResults = res.data.totalRows;
          someService.pageNumbers = someService.pages(res.data.totalRows,10);
        })
      }
});

在您的測試中, this.anotherService.resources的值仍為{} ,因為在測試運行之后 ,以下then回調中的代碼是異步運行的:

someService.getItemList($stateParams.id,'F', start).then(function (res){
    anotherService.resources = res.data.rows;
    console.log(anotherService.resources)
    someService.numResults = res.data.totalRows;
    someService.pageNumbers = someService.pages(res.data.totalRows,10);
})

盡管在getItemList您可以同步解決promise

getItemList: function(res) {
    var deferred = $q.defer();
    deferred.resolve({
        data: {
            totalRows: 2,
            rows: 3,
        }
    });
    return deferred.promise;
},

...實際上,當您調用deferred.resolve時,它不會立即在promise上調用then函數。 當您想到它時,也沒有任何意義,因為必須先將諾言返回給呼叫者,然后呼叫者才能附加“ then再回叫給它。 相反,它異步地調用then回調,即在所有當前執行的代碼完成后都帶有一個空的調用棧。 這包括您的測試代碼! Angular文檔中所述

then(successCallback, errorCallback, notifyCallback) –無論何時或將要解決或拒絕promise, then在結果可用時立即異步調用成功或錯誤回調之一。

以及同一文檔中的測試示例

 // Simulate resolving of promise deferred.resolve(123); // Note that the 'then' function does not get called synchronously. // This is because we want the promise API to always be async, whether or not // it got called synchronously or asynchronously. 

如何測試異步代碼

首先,您可以讓getNextPage返回一個諾言-與getItemList返回的諾言相同:

function getNextPage(options){
    var o = options || {selected:1};
    var start = (o.selected-1)*10 || 0;
    someService.currPage = o.selected;
    // store the promise in a variable
    var prom = someService.getItemList($stateParams.id,'F', start);
    prom.then(function (res){
        anotherService.resources = res.data.rows;
        console.log(anotherService.resources)   // this shows LOG: 3 in terminal
        someService.numResults = res.data.totalRows;
        someService.pageNumbers = someService.pages(res.data.totalRows,10);
    });
    return prom; // return that promise
}

然后,您可以在getNextPage()上使用then ,它將與附加的其他then回調依次執行,因此在上述代碼的then回調之后。

然后可以使用Jasmine的done來告訴Jasmine測試是異步的,以及何時完成:

// The presence of the `done` parameter indicates to Jasmine that 
// the test is asynchronous 
it('should run the getNextPage function', function(done) { 
    this.scope.getNextPage().then(function () {
        this.scope.$digest();
        console.log(this.anotherService.resources);
        expect(this.anotherService.resources).toEqual(3);
        done(); // indicate to Jasmine that the asynchronous test has completed
    });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM