Sinon: Korrekte Verwendung von sinons fakeXMLHttpRequest in node.js

Erstellt am 1. Sept. 2015  ·  7Kommentare  ·  Quelle: sinonjs/sinon

Ich erstelle das Javascript-Modul XMLHttpRequest, um JSON-Daten vom Server zu erhalten. Hier ist der Code:

(function() {
  var makeRequest = function(url,callback,opt) {
    var xhr;
    if (XMLHttpRequest) { // Mozilla, Safari, ...
      xhr = new XMLHttpRequest();
    } else if (ActiveXObject) { // IE
      try {
        xhr = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (e) {
        try {
          xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (e) {}
      }
    }

    if (!xhr) {
      callback.call(this,
        'Giving up :( Cannot create an XMLHTTP instance',
        null);
      return false;
    }
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          var data = xhr.responseText;
          if(opt && !opt.raw) {
            try {
              data = JSON.parse(data);
            } catch (e) {
              callback.call(this, e,null);
              return;
            }
          }
          callback.call(this,null,data);
        } else {
          callback.call(this,
            'There was a problem with the request.',
            null);
        }
      }
    };
    var params = '';
    if (opt && opt.params && typeof(opt.params) == 'object') {
      for( var key in opt.params) {
        params += encodeURIComponent(opt.params[key]);
      }
    }
    var method = opt && opt.method ? opt.method : 'GET';
    if (method == 'GET') {
      url = params.length > 0 ? url+'?'+params : url;
      xhr.open('GET', url);
      xhr.send();
    } else if (method == 'POST') {
      var data = opt && opt.data ? opt.data : params;
      xhr.open('POST', url);
      xhr.send(JSON.stringify(data));
    }
    return xhr;
  }

  if(typeof module !== 'undefined' && module.exports) {
    module.exports = makeRequest;
  }
  if(typeof window!== 'undefined') {
    window.getJSONData = makeRequest;
  }
})();

Ich schreibe den Testfall dafür auf nodejs mit Mocha und Sinon. Verwenden von Sinons fakeXMLHttpRequest zum Testen des Moduls. Hier der Testcode:

var expect = require('chai').expect,
  getJSON = require('../'),
  sinon = require('sinon');

describe('get-json-data test the request', function() {
  beforeEach(function() {
    this.xhr = sinon.useFakeXMLHttpRequest();
    var requests = this.requests = [];

    this.xhr.onCreate = function (xhr) {
      requests.push(xhr);
    };
  });
  afterEach(function() {
    this.xhr.restore();
  });

  it('get json data', function() {
    var callback = sinon.spy();
    getJSON('/some/json', callback);
    expect(this.requests.length).to.equal(1);
    this.requests[0].respond(200,
      {"Content-Type": "application/json"},
      '{"id": 1, "name": "foo"}');
    sinon.assert.calledWith(callback, {"id": 1, "name": "foo"});
  });
});

Beim Ausführen des Tests erhalte ich die Fehlermeldung:

ReferenceError: XMLHttpRequest is not defined

Und es scheint richtig zu sein, da es in nodejs keine XMLHttpRequest-Klasse/-Funktion gibt. Aber Sinons fakeXMLHttpRequest soll das nicht tun. Ich dachte, in Sinons Setup (Mocha's beforeEach) erstellen wir mit fakeXMLHttpRequest einen gefälschten XMLHttpRequest. Bitte schlagen Sie vor, was ich falsch mache? Oder was wäre der richtige Weg, Sinon zu verwenden, um mein Modul bei nodejs zu testen?

Hilfreichster Kommentar

Für diejenigen, die Ajax in Node nur mit Mocha und Sinon testen möchten, müssen Sie nur global.XMLHttpRequest auf sinon.useFakeXMLHttpRequest() . Hier ist ein Beispiel: https://github.com/scriptare/compago-ajax/blob/master/tests/unit.test.js#L36

Alle 7 Kommentare

Es gibt keine "richtige" Möglichkeit, ein Modul zu testen, das DOM-APIs mit Node verwendet, das keine Vorstellung von DOM hat. Aber es gibt Möglichkeiten, Ihr Ziel zu erreichen. Der beste Weg, um loszulegen, besteht wahrscheinlich darin, Karma so einzurichten, dass Ihre Tests in PhantomJS oder Desktop-Browsern ausgeführt werden. Das würde Ihren Code in einem Browser testen - der tatsächlichen Umgebung, in der er verwendet wird!

Wenn Sie darauf bestehen, den Code _in Node_ zu testen, können Sie jsdom ausprobieren , wodurch die DOM-API zum aktuellen Kontext

var jsdom = require('mocha-jsdom')
var expect = require('chai').expect

describe('mocha tests', function () {

  jsdom()

  it('has document', function () {
    var div = document.createElement('div')
    expect(div.nodeName).eql('DIV')
  })

})

Es scheint, dass es andere gibt, die jsdom und sinon.js verwenden, also sollten Sie nicht zu viele Probleme haben.

Danke @fatso83 Also werde ich versuchen Karma mit PhantomJS zu implementieren.

@gagan-bansal Wenn Sie einen Setup-Code benötigen, um loszulegen, können Sie hier beginnen

@fatso83 danke für den Hinweis, ich werde es überprüfen.

Für diejenigen, die Ajax in Node nur mit Mocha und Sinon testen möchten, müssen Sie nur global.XMLHttpRequest auf sinon.useFakeXMLHttpRequest() . Hier ist ein Beispiel: https://github.com/scriptare/compago-ajax/blob/master/tests/unit.test.js#L36

@zandaqo danke für das Update.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen