使用mocha html5文件api进行Javascript测试?

我在网站上有一个简单的图片上传器和一个JavaScript函数,它使用FileReader并将图像转换为base64,以便将其显示给用户,而无需将其上传到实际服务器。

function generateThumb(file) {
    var fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.onload = function (e) {
        // Converts the image to base64
        file.dataUrl = e.target.result;
    };
}

现在我正在尝试使用MochaChai为此方法编写测试。 我的想法是,我想检查是否已成功创建file.dataUrl并且它是base64。 所以我想在测试环境中以某种方式嘲笑本地文件(不知道如何做到这一点)。 或者我不应该测试这一点,并假设这是行得通的?


答案在这里取决于一点。 您的“generateThumbs”方法是否具有加载文件内容并将其分配给传入对象的属性的其他逻辑? 还是有其他逻辑,如从图像数据生成缩略图,读出文件属性并将它们分配给文件对象? 等等?

如果是这样,那么我会建议你用你自己的模拟FileReader对象,这样你就可以控制你的测试结果。 但是,它不是您想要测试的FileReaders功能,而是您自己的逻辑。 所以你应该假设FileReader工作并测试你的代码依赖于它。

现在,由于您发布的方法有点小,在这种情况下,我会假设它的工作原理,重命名该方法并测试其余代码。 但是有这样一个模拟的地方,我必须承认找出如何模拟事件目标是非常有趣的,所以我将在这里举一个例子,用你的方法作为基础:

//This implements the EventTarget interface
//and let's us control when, where and what triggers events
//and what they return
//it takes in a spy and some fake return data

var FakeFileReader = function(spy, fakeData) {
    this.listeners = {};
    this.fakeData = fakeData;
    this.spy = spy;
    this.addEventListener('load', function () {
        this.spy.loaded = true;
    });
};
//Fake version of the method we depend upon
FakeFileReader.prototype.readAsDataURL = function(file){
    this.spy.calledReadAsDataURL = true;
    this.spy.file = file;
    this.result = this.fakeData;
    this.dispatchEvent({type:'load'}); //assume file is loaded, and send event
};
FakeFileReader.prototype.listeners = null;
FakeFileReader.prototype.addEventListener = function(type, callback) {
    if(!(type in this.listeners)) {
        this.listeners[type] = [];
    }
    this.listeners[type].push(callback);
};

FakeFileReader.prototype.removeEventListener = function(type, callback) {
    if(!(type in this.listeners)) {
        return;
    }
    var stack = this.listeners[type];
    for(var i = 0, l = stack.length; i < l; i++) {
        if(stack[i] === callback){
            stack.splice(i, 1);
            return this.removeEventListener(type, callback);
        }
    }
};

FakeFileReader.prototype.dispatchEvent = function(event) {
    if(!(event.type in this.listeners)) {
        return;
    }
    var stack = this.listeners[event.type];
    event.target = this;
    for(var i = 0, l = stack.length; i < l; i++) {
        stack[i].call(this, event);
    }
};

// Your method

function generateThumb(file, reader){
    reader.readAsDataURL(file);
    reader.addEventListener('load', function (e) {
        file.dataUrl = base64(e.target.result);
    });

}

现在我们有一个很好的小对象,就像FileReader一样,但是我们可以控制它的行为,现在我们可以使用我们的方法并注入它,从而使我们能够使用这个模拟器进行测试,并将其用于生产。

所以我们现在可以编写出色的单元测试来测试这一点:我假设你有摩卡和柴安装

describe('The generateThumb function', function () {
    var file = { src: 'image.file'};
    var readerSpy = {};
    var testData = 'TESTDATA';
    var reader    = new FakeFileReader(readerSpy, testData);
    it('should call the readAsDataURL function when given a file name and a FileReader', function () {
        generateThumb(file, reader);
        expect(readerSpy.calledReadAsDataURL).to.be.true;
        expect(readerSpy.loaded).to.be.true;
    });
    it('should load the file and convert the data to base64', function () {
        var expectedData = 'VEVTVERBVEE=';
        generateThumb(file, reader);
        expect(readerSpy.file.src).to.equal(file.src);
        expect(readerSpy.file.dataUrl).to.equal(expectedData);
    });
});

这是一个可用的JSFiddle示例:https://jsfiddle.net/workingClassHacker/jL4xpwwv/2/

这里的好处是你可以创建这个模拟的几个版本:

  • 当给出正确的数据时会发生什么?
  • 当给出不正确的数据时会发生什么?
  • 回调从未被调用时会发生什么?
  • 当太大的文件被放入时会发生什么?
  • 当某个MIME类型被放入时会发生什么?
  • 如果你需要的只是一个事件,你可以大量简化模拟的过程:

    function FakeFileReader(spy, testdata){
        return {
            readAsDataURL:function (file) {
                spy.file = file;
                spy.calledReadAsDataURL = true;
                spy.loaded = true;
                this.target = {result: testdata};
                this.onload(this);
            }
        };
    }
    
    function generateThumb(file, reader){
        reader.onload = function (e) {
            file.dataUrl = base64(e.target.result);
        };
        reader.readAsDataURL(file);
    }
    

    我是如何做到这一点的。 并创建其中几个用于不同的目的。

    简单版本:https://jsfiddle.net/workingClassHacker/7g44h9fj/3/

    链接地址: http://www.djcxy.com/p/27205.html

    上一篇: Javascript testing with mocha the html5 file api?

    下一篇: static const already defined