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 完全相同的内容:

这也返回了正确的结果。

总结

关于发生了什么的任何线索?

答案: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
)

现在可以按预期工作了。