我得到了类似这些代码的内容:
jQuery('.js-img-input').on('change', handleNewFiles);
var handleNewFiles = function(event) {
var fileList = event.target.files;
loadFileList(fileList);
};
var loadFileList = function(fileList) {
jQuery(fileList).each(function(key, file) {
readFileAsync(file);
});
}
var readFileAsync = function(file) {
var fileReader = new FileReader();
fileReader.addEventListener("load", function(event) {
file.result = event.target.result;
saveFile(file);
});
fileReader.readAsDataURL(file);
};
所有方法都是jQuery函数内部的私有方法,我不打算将“handleNewFiles”公开用于测试目的。
我想用这样的东西测试这些线:
it('should create a fileReader', function(){
spyOn(window, 'FileReader').and.returnValue({
addEventListener: function(){},
readAsDataURL: function(){}
});
jQuery('.js-img-input').trigger('change');
expect(window.FileReader).toHaveBeenCalled();
});
但是我如何将一些虚拟数据导入 event.target.files ?
答案 0 :(得分:3)
好吧我找到了解决方案。您无法使用文件创建伪造的本机事件,出于安全考虑,这是一件好事。但就我而言,解决方案看起来像这样:
it('should create a fileReader', function(){
var onChangeCallback;
spyOn(jQuery.fn, 'on').and.callFake(function(eventName, callback){
if(eventName === 'change'){
onChangeCallback = callback;
}
});
spyOn(window, 'FileReader').and.returnValue({
addEventListener: function(){},
readAsDataURL: function(){}
});
onChangeCallback({target:{files:[1,2,3]}});
expect(window.FileReader).toHaveBeenCalled();
});
答案 1 :(得分:1)
这篇文章可能有帮助
http://nerds.intuo.io/2016/05/12/mocking-file-uploads-in-javascript.html
function fillInFileInput(selector, file) {
// Get the input
let input = jQuery(selector);
// Get out file options
let { name, type, content } = file;
// Create a custom event for change and inject target
let event = jQuery.Event('change', {
target: {
files: [{
name: name, type: type
}]
}
});
// Stub readAsDataURL function
let stub = sinon.stub(FileReader.prototype, 'readAsDataURL', function() {
this.onload({ target: { result: content }});
});
// Trigger event
input.trigger(event);
// We don't want FileReader to be stubbed for all eternity
stub.restore();
}

答案 2 :(得分:0)
我发布了一个基于Jakob答案的略微修改过的解决方案。我需要一些细微的修改才能让它适合我。这对我使用“angular”:“1.0.6”,“jasmine-node”:“1.3.1”,“jquery”:“1.10.0”
var onChangeCallback;
spyOn(jQuery.fn, 'on').andCallFake(function(eventName, selector, callback){
if(eventName === 'change'){
onChangeCallback = callback;
}
});
spyOn(window, 'FileReader').andReturn({
addEventListener: function(){},
readAsDataURL: function(){}
});
onChangeCallback({currentTarget: {files:[{size: 4000}], value: 'asd'}});
答案 3 :(得分:0)
虽然您无法为fileInput.files
分配值,但是您可以用自己的属性替换该属性,从而实现相同的目的:
it('should create a fileReader', () => {
const fileInput = $('input[type=file]');
const fileInputElement = fileInput.get(0);
Object.defineProperty(fileInputElement, 'files', {
value: [{name: 'file.txt'}],
writable: false,
});
fileInput.trigger('input').trigger('change');
// expect outputs...
});
这比创建自己的事件对象要好一些,因为它可以更精确地模拟真实环境。