我需要测试一个从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);
}());
我正在使用带有Jasmine的Karma来测试套装。我的测试套装是这样的:
/*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 :(得分:2)
要测试AngularJS中$ q提供程序的任何用法,您必须使摘要周期允许任何Promise在引擎盖下解析。您应该尝试以下方法:
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();
}
修改强>
在回复评论时,您还需要创建$ scope变量,如下所示:
var SourceLoaderService, $scope;
beforeEach(function () {
inject(function ($injector) {
SourceLoaderService = $injector.get('SourceLoaderService');
$scope = $injector.get('$rootScope').$new();
});
});
答案 1 :(得分: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 :(得分:2)
在你的" it
" function将导致测试执行异步调用。
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供参考。
答案 3 :(得分:1)
图像加载可能比默认超时间隔花费更多时间
尝试这样的事情:
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000
。
它设置等待done()
呼叫到30秒的时间。
答案 4 :(得分:1)
Array.insert不是一个函数。您可以扩展Array以获得插入功能。但是有一种更简单的方法。只需调用图像[:N] =图像或只使用Promise.all
:
这将简化您的loadImages
功能:
var loadImages = function() {
var loadImagePromises = urls.map(function(url) {
return loadImage(url)
})
return Promise.all(loadImagePromises)
}