Ajax : 使用 Karma 时为空 json 响应
Ajax : empty json response when using Karma
TL;DR : Karma 是否篡改了 运行 正在测试时发送的 ajax 请求?
上下文
我目前正在为 front-end javascript 应用程序编写 unit-tests。我正在使用 Karma 0.12.31 到 运行 测试,我使用的唯一与这个问题相关的前端库是 jQuery.
我有一个非常简单的 class object 负责从后端获取和缓存结果 API :
function APIReader(baseUrl) {
this.baseUrl = baseUrl;
this.cache = {};
}
APIReader.prototype.updateCache = function(uuid) {
var that = this;
$.ajax({
url : this.baseUrl+uuid,
dataType : 'json',
async : false,
success : function (data) {
that.cache[uuid] = data;
},
error : function(jqxhr, status, err) {
that.cache[uuid] = undefined;
}
});
};
APIReader.prototype.get = function(uuid) {
if (!(uuid in this.cache)) this.updateCache(uuid);
return this.cache[uuid];
};
以下代码片段在开发服务器上非常有效:
var ar = new APIReader('http://server/api/endpoint/');
console.log(ar.get('18fc7dc1-7698-4b8e-900e-8262c1393067'));
问题
但是,当使用 Karma 进行测试时,请说:
it('should work', function() {
var ar = new APIReader('http://server/api/endpoint/');
expect(ar.get('some-uuid')).toEqual({
... some object ...
});
});
我收到此错误:1) Expected null to be Object({ ... some object ... }).
。
我研究了一段时间,浏览器 (Firefox 35) 收到的 ajax 响应的 body 似乎是空的。
我很确定 API(用 django and django-rest-framework) works well as httpie 编写)为同一端点提供正确的 (non-enpty) 结果。
实际上,我已经尽可能重现了 Firefox 使用 cURL 使用的 headers 完全相同的内容:
这也返回了正确的结果。
总结
- 我非常有信心 API 运行良好
- 我相信
APIReader
片段运行良好(内容不多,它在开发中给出了正确的结果)
- 我 假设 Karma 中有一些东西篡改了 ajax 请求(擦除 body 或其他东西)但是他们没有太多可用的文档website 我找不到类似的东西。
关于发生了什么的任何线索?
答案:CORS。
这一切似乎都是因为 API 服务器不允许测试服务器执行 cross-origin 请求。
django 应用程序 (API) 使用 django-cors-headers 生成 CORS headers。我没有意识到的是,基于端口的主机是有区别的:
CORS_ORIGIN_WHITELIST = (
'localhost',
'other-domain',
)
不允许 localhost:4000
上的测试服务器 运行 发送 CORS 请求。我必须添加以下内容:
CORS_ORIGIN_WHITELIST = (
'localhost',
'other-domain',
'localhost:4000' # Karma test
)
现在可以按预期工作了。
TL;DR : Karma 是否篡改了 运行 正在测试时发送的 ajax 请求?
上下文
我目前正在为 front-end javascript 应用程序编写 unit-tests。我正在使用 Karma 0.12.31 到 运行 测试,我使用的唯一与这个问题相关的前端库是 jQuery.
我有一个非常简单的 class object 负责从后端获取和缓存结果 API :
function APIReader(baseUrl) {
this.baseUrl = baseUrl;
this.cache = {};
}
APIReader.prototype.updateCache = function(uuid) {
var that = this;
$.ajax({
url : this.baseUrl+uuid,
dataType : 'json',
async : false,
success : function (data) {
that.cache[uuid] = data;
},
error : function(jqxhr, status, err) {
that.cache[uuid] = undefined;
}
});
};
APIReader.prototype.get = function(uuid) {
if (!(uuid in this.cache)) this.updateCache(uuid);
return this.cache[uuid];
};
以下代码片段在开发服务器上非常有效:
var ar = new APIReader('http://server/api/endpoint/');
console.log(ar.get('18fc7dc1-7698-4b8e-900e-8262c1393067'));
问题
但是,当使用 Karma 进行测试时,请说:
it('should work', function() {
var ar = new APIReader('http://server/api/endpoint/');
expect(ar.get('some-uuid')).toEqual({
... some object ...
});
});
我收到此错误:1) Expected null to be Object({ ... some object ... }).
。
我研究了一段时间,浏览器 (Firefox 35) 收到的 ajax 响应的 body 似乎是空的。
我很确定 API(用 django and django-rest-framework) works well as httpie 编写)为同一端点提供正确的 (non-enpty) 结果。
实际上,我已经尽可能重现了 Firefox 使用 cURL 使用的 headers 完全相同的内容:
这也返回了正确的结果。
总结
- 我非常有信心 API 运行良好
- 我相信
APIReader
片段运行良好(内容不多,它在开发中给出了正确的结果) - 我 假设 Karma 中有一些东西篡改了 ajax 请求(擦除 body 或其他东西)但是他们没有太多可用的文档website 我找不到类似的东西。
关于发生了什么的任何线索?
答案:CORS。
这一切似乎都是因为 API 服务器不允许测试服务器执行 cross-origin 请求。
django 应用程序 (API) 使用 django-cors-headers 生成 CORS headers。我没有意识到的是,基于端口的主机是有区别的:
CORS_ORIGIN_WHITELIST = (
'localhost',
'other-domain',
)
不允许 localhost:4000
上的测试服务器 运行 发送 CORS 请求。我必须添加以下内容:
CORS_ORIGIN_WHITELIST = (
'localhost',
'other-domain',
'localhost:4000' # Karma test
)
现在可以按预期工作了。