正确使用 sinon 的假 XMLHttpRequest
correct usage of sinon's fake XMLHttpRequest
我正在创建 XMLHttpRequest javascript 模块以从服务器获取 JSON 数据。这是代码:
(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;
}
})();
现在我正在使用 Mocha 和 Sinon 在 nodejs 上为此编写测试用例。使用Sinon的fakeXMLHttpRequest来测试模块,测试代码在这里:
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"});
});
});
在 运行 测试中出现错误:
ReferenceError: XMLHttpRequest is not defined
这似乎是正确的,因为 nodejs 中没有 XMLHttpRequest class/function。但是 Sinon 的 fakeXMLHttpRequest 不应该这样做吗?我认为在 Sinon 的设置(Mocha 的 beforeEach)中,我们正在用 fakeXMLHttpRequest 替换本机 XMLHttpRequest。
请建议我做错了什么?或者在 nodejs 上测试我的模块的正确方法是什么?
因为您 运行 在浏览器环境之外,所以没有 XMLHttpRequest
对象。由于您正在用 Sinon 模拟它,您可以做的是在 beforeEach
调用中声明一个伪造的全局函数。
global.XMLHttpRequest = sinon.useFakeXMLHttpRequest();
我这样做是为了覆盖 XMLHttpRequest(请参阅我的问答 ):
var FakeXMLHTTPRequests = require('fakexmlhttprequest')
var requests = []
XMLHttpRequest = function() {
var r = new FakeXMLHTTPRequests(arguments)
requests.push(r)
return r
}
我正在创建 XMLHttpRequest javascript 模块以从服务器获取 JSON 数据。这是代码:
(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;
}
})();
现在我正在使用 Mocha 和 Sinon 在 nodejs 上为此编写测试用例。使用Sinon的fakeXMLHttpRequest来测试模块,测试代码在这里:
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"});
});
});
在 运行 测试中出现错误:
ReferenceError: XMLHttpRequest is not defined
这似乎是正确的,因为 nodejs 中没有 XMLHttpRequest class/function。但是 Sinon 的 fakeXMLHttpRequest 不应该这样做吗?我认为在 Sinon 的设置(Mocha 的 beforeEach)中,我们正在用 fakeXMLHttpRequest 替换本机 XMLHttpRequest。 请建议我做错了什么?或者在 nodejs 上测试我的模块的正确方法是什么?
因为您 运行 在浏览器环境之外,所以没有 XMLHttpRequest
对象。由于您正在用 Sinon 模拟它,您可以做的是在 beforeEach
调用中声明一个伪造的全局函数。
global.XMLHttpRequest = sinon.useFakeXMLHttpRequest();
我这样做是为了覆盖 XMLHttpRequest(请参阅我的问答
var FakeXMLHTTPRequests = require('fakexmlhttprequest')
var requests = []
XMLHttpRequest = function() {
var r = new FakeXMLHTTPRequests(arguments)
requests.push(r)
return r
}