2015-06-26 4 views
7

Ich habe einfache Bild-Uploader in einer Website und eine Javascript-Funktion, die FileReader verwendet und konvertiert Bild zu Base64, um es für Benutzer anzuzeigen, ohne es auf den tatsächlichen Server zu laden.Javascript-Test mit Mocha die HTML5-Datei API?

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

Jetzt versuche ich, Tests für diese Methode unter Verwendung von Mocha und Chai zu schreiben. Mein Denken ist, dass ich überprüfen möchte, ob die file.dataUrl erfolgreich erstellt wurde und es Base64 ist. Also würde ich gerne die lokale Datei irgendwie in Testumgebung überspielen (nicht sicher, wie das geht). Oder sollte ich das überhaupt nicht testen und davon ausgehen, dass das funktioniert?

+0

ich auch das Gleiche fragen. – frogbandit

Antwort

3

Die Antwort hier hängt ein wenig ab. Hat Ihre "generateThumbs" -Methode eine andere Logik als den Inhalt einer Datei zu laden und ihn einer Eigenschaft eines übergebenen Objekts zuzuweisen? Oder hat es eine andere Logik, etwa das Erzeugen der Miniatur aus den Bilddaten, das Auslesen von Dateieigenschaften und das Zuordnen dieser zum Dateiobjekt? und so weiter?

Wenn ja, dann würde ich vorschlagen, dass Sie das FileReader-Objekt mit Ihren eigenen mock-out, so dass Sie Ihre Testergebnisse steuern können. Es ist jedoch nicht die FileReaders-Funktionalität, die Sie testen möchten, es ist Ihre eigene Logik. Sie sollten also davon ausgehen, dass FileReader funktioniert und testen, dass der von Ihnen abhängige Code funktioniert.

Nun, da die von Ihnen gepostete Methode ein bisschen klein war, würde ich in diesem Fall einfach davon ausgehen, dass es funktioniert, benennen Sie die Methode um und arbeiten Sie daran, den Rest Ihres Codes zu testen. Aber es ist ein Ort für ein solches Mock hat, und ich muss zugeben, dass es ganz lustig war, herauszufinden, wie das Ereignisziel zu verspotten, so dass ich hier ein Beispiel geben, mit Ihrer Methode als Grundlage:

//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); 
    }); 

} 

Jetzt haben wir ein nettes kleines Objekt, das sich wie ein FileReader verhält, aber wir kontrollieren sein Verhalten, und wir können nun unsere Methode benutzen und sie injizieren, so dass wir diesen Mock zum Testen und zur echten Produktion verwenden können.

So können wir schreiben jetzt schön Unit-Tests dies zu testen: Ich nehme an, Sie haben Mokka und chai Setup

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); 
    }); 
}); 

Hier ist ein funktionierendes JSFiddle Beispiel: https://jsfiddle.net/workingClassHacker/jL4xpwwv/2/

Die Vorteile hier sind Sie können mehrere Versionen dieses Mocks erstellen:

  • Was passiert, wenn die richtigen Daten angegeben werden?
  • Was passiert, wenn falsche Daten angegeben werden?
  • Was passiert, wenn der Rückruf nie aufgerufen wird?
  • Was passiert, wenn eine zu große Datei eingefügt wird?
  • Was passiert, wenn ein bestimmter Mime-Typ eingefügt wird?

Sie können offcourse massiv Mock vereinfachen, wenn alles, was Sie brauchen, dass ein Ereignis ist:

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); 
} 

Welche ist, wie ich dies tatsächlich tun. Und erstellen Sie mehrere davon für verschiedene Zwecke.

Einfache Version: https://jsfiddle.net/workingClassHacker/7g44h9fj/3/