2016-04-27 74 views
4

我需要測試從url加載圖像的AngularJs服務。這裏是我的服務:茉莉花:超時 - 異步回調未在超時範圍內調用

/*global angular, Image*/ 
(function() { 
    'use strict'; 
    function SourceLoader($q, $log) { 

    /** 
    * Load an image from url and return a promise which is resolved when image is loading is done. 
    * It return the images object as resolved promise. 
    * @param url source of the image 
    * @returns {Promise} unresolved promise of image. 
    */ 
    function loadImage(url) { 
     var deferred = $q.defer(), 
      image = new Image(); 
     image.onload = function() { 
     deferred.resolve(image); 
     }; 
     image.onerror = function (error) { 
     $log.error('Error while loading image from url ' + url); 
     $log.debug(error); 
     deferred.reject(error); 
     }; 
     image.src = url; 
     return deferred.promise; 
    } 

    /** 
    * Load images from and array of urls nd return the array of loaded images. The order of returned 
    * images is same as the order of passed urls. 
    * @param urls sources if images in array. 
    * @returns {Promise} unresolved promise. 
    */ 
    function loadImages(urls) { 
     var count = 0, deferred = $q.defer(), 
      images = [], 
      callback = function (image, index) { 
      images.insert(index, image); 
      count += 1; 
      if (count === urls.length) { 
       //All images are loaded. High time to resolve promise. 
       deferred.resolve(images); 
      } 
      }; 
     urls.forEach(function (url, index) { 
     var image = new Image(); 
     image.onload = function() { 
      callback(image, index); 
     }; 
     image.onerror = function (event) { 
      $log.error('Error while loading image from url ' + url); 
      $log.debug(event); 
      callback(event, index); 
     }; 
     image.src = url; 
     }); 
     return deferred.promise; 
    } 

    return { 
     loadImage: loadImage, 
     loadImages: loadImages 
    }; 
    } 

    var app = angular.module('myCanvasModule'), 
     requires = [ 
     '$q', 
     '$log', 
     SourceLoader 
     ]; 
    app.factory('SourceLoaderService', requires); 
}()); 

我使用噶茉莉爲測試服。我的測試服是這樣的:

/*global describe, TestUtils, beforeEach, it, module, inject, SourceLoaderServiceTestData, done, expect*/ 
(function() { 
    'use strict'; 
    describe('myCanvasModule: Services: SourceLoaderService-->\n\t', function() { 
    var SourceLoaderService, getTestData; 

    getTestData = TestUtils.getTestData.bind(null, SourceLoaderServiceTestData); 

    beforeEach(function() { 
     module('myCanvasModule'); 
    }); 

    beforeEach(function() { 
     inject(function ($injector) { 
     SourceLoaderService = $injector.get('SourceLoaderService'); 
     }); 
    }); 

    describe('SourceLoaderService.loadImage-->\n\t', function() { 
     var testData; 
     beforeEach(function() { 
     testData = getTestData('loadImage'); 
     }); 

     it('should load the source and return the image as response', function (done) { 
     var image; 
     SourceLoaderService.loadImage(testData.validSource).then(function (response) { 
      image = response; 
      done(); 
      console.log('called'); 
     },function (error) { 
      console.log('called', error); 
      done(); 
     }); 
     }); 

    }); 

    }); 
}()); 

當我運行測試服我得到:

錯誤:超時 - 異步回調不被jasmine.DEFAULT_TIMEOUT_INTERVAL指定的超時時間內調用。

我不知道發生了什麼問題。我是Karma和Jasmine的新手。謝謝您的幫助。

+0

也許使用Promise.all作爲loadImages中的返回語句。那麼你可以跳過你的記數簿。 – lipp

+0

抱歉沒有找到你。 –

+0

是您的圖片源網址有效嗎? – lipp

回答

1

圖像加載可能需要比默認超時間隔更多的時間。
嘗試類似這樣:
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000。 它設定時間等待done()呼叫到30秒。

+0

不起作用。它說斷開連接 –

1

Array.insert只是不是一個函數。您可以擴展數組,使其具有當然的插入功能。但是有一種更簡單的方法。要麼只是調用圖像[:N =圖像或只使用Promise.all

這將簡化您的loadImages功能很多:

var loadImages = function() { 
    var loadImagePromises = urls.map(function(url) { 
    return loadImage(url) 
    }) 
    return Promise.all(loadImagePromises) 
} 
+0

我已經創建了我自己的Array.prototye.insert。無論如何,我可以隨時做任何反應。我擔心的是如何測試loadImage –

+0

好。不好意思誤解 – lipp

+0

不用擔心。感謝您的重構loadImages –

2

爲了測試在AngularJS的$ Q提供的任何使用,您將有使摘要循環允許任何承諾解決。你應該嘗試以下操作:

it('should load the source and return the image as response', function (done) { 
    var image; 

    SourceLoaderService.loadImage(testData.validSource) 
    .then(function (response) { 
     // ... success check 
    },function (error) { 
     // ... error check 
    }); 

    // Call apply for the above Promise to resolve 
    $scope.$apply(); 
} 

編輯:

在迴應評論,您還需要創建$範圍變量,如下所示:

var SourceLoaderService, $scope; 

beforeEach(function() { 
    inject(function ($injector) { 
    SourceLoaderService = $injector.get('SourceLoaderService'); 
    $scope = $injector.get('$rootScope').$new(); 
    }); 
}); 
+0

服務的任何地方都沒有範圍,但您仍然建議如此嘗試,但我仍然遇到同樣的錯誤。 :( –

+0

我已經添加了一些關於如何定義'$ scope'的實例的信息。 –

+0

我正在做同樣的事情。 –

2

我能夠重現這一點,也能夠成功運行測試用例。我不知道爲什麼你需要做的東西,但下面的變化爲我工作。

it('should load the source and return the image as response', function() { 
    var image; 
    sourceLoader.loadImage('https://s0.2mdn.net/viewad/5406241/6-jira-software_therapy-agile-tools_free-trial_static_728x90.png').then(function (response) { 
    image = response; 
    //setTimeout(done(), 60000); 
    console.log('called'); 
    },function (error) { 
    console.log('called', error); 
    //done(); 
    }); 
}); 
2

在你的「it」功能的參數會導致測試執行異步調用。

it('should load the source and return the image as response', function() { 
    var image; 
    sourceLoader.loadImage(testData.validSource).then(function (response) { 
    image = response; 
    console.log('called'); 
    },function (error) { 
    console.log('called', error); 
    }); 
}); 

爲了使用「done」回調測試異步調用,你應該將一些代碼爲「beforeEach」功能。這裏有一個link供參考。

+0

在我的情況下,我無法得到我應該移動的部分在beforeEach你能請多解釋一下嗎? –

相關問題