如何使用Jasmine测试XMLHttpRequest

14

如何在没有jQuery的情况下测试XMLHttpRequest或纯Javascript AJAX上的onreadystatechange?我这样做是因为我正在开发Firefox扩展。我猜我必须使用spy,但无法弄清楚原因是我的ajax不会返回任何东西。


    提交 : function() {
        var url = window.arguments[0];
        var request = new XMLHttpRequest();
        request.open("POST", 'http://'+this.host+'/doSomething', true);
        request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        request.send("param="+param+"&emotions="+this.getParams());
        request.onreadystatechange = function() {
            if(this.readyState == 4) {
                // alert(this.responseText);
            }
        };
}
该函数的功能是发送POST请求到指定url并将参数传递给服务器。 使用XMLHttpRequest对象,通过设置请求头和请求体来配置请求。 将参数编码为x-www-form-urlencoded格式,然后使用send()方法将其发送到服务器。 函数还设置了一个回调函数以在完成请求后执行特定操作。

1
那个是使用jQuery的,但我正在尝试使用纯XMLHttpRequest。 - toy
当然可以,使用SininJS的mocking框架的答案也适用于你的情况。 - Andreas Köberle
抱歉,我没想到SininJS可以做到那个。谢谢!我会尝试的。 - toy
6个回答

39

还有这个呢?

beforeEach(function() {
  // spyOn(XMLHttpRequest.prototype, 'open').andCallThrough(); // Jasmine 1.x
  spyOn(XMLHttpRequest.prototype, 'open').and.callThrough(); // Jasmine 2.x
  spyOn(XMLHttpRequest.prototype, 'send');
});

...

it("should call proper YQL! API", function() {
  podcast.load_feed('http://www.faif.us/feeds/cast-ogg/');

  expect(XMLHttpRequest.prototype.open).toHaveBeenCalled();
});

不需要使用任何外部库即可实现纯茉莉花。


2
这对我有用。但如何模拟像onError、onLoad等xhr响应处理程序呢? - sonam
太棒了,这帮了我大忙。 - Matt West

11

Jasmine有自己的Ajax模拟库,名为ajax.js,您可以在这里找到相关信息。


谢谢@taro!我使用jasmine-ajax,现在我的测试用例看起来非常简单!演示:https://github.com/piecioshka/test-angular-services-testing/blob/master/src/app/photos.service.spec.ts#L84 - piecioshka

6

5
你可以用以下方式进行测试:
it("should make XHR request", function() {

   // arrange

    var xhr = {
        open: jasmine.createSpy('open')
    };

    XMLHttpRequest = jasmine.createSpy('XMLHttpRequest');
    XMLHttpRequest.and.callFake(function () {
        return xhr;
    });

    // act

    submit();

    // assert

    expect(xhr.open).toHaveBeenCalled(); 
});

这可能是 JavaScript 项目的解决方案。在我的 Angular 应用中,TypeScript 抱怨覆盖了被推断为 XMLHttpRequest 接口的 XMLHttpRequest。 - piecioshka

1

jasmine-ajax提供。要为单个规范进行模拟,请使用withMock

  it("allows use in a single spec", function() {
    var doneFn = jasmine.createSpy('success');
    jasmine.Ajax.withMock(function() {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function(args) {
        if (this.readyState == this.DONE) {
          doneFn(this.responseText);
        }
      };

      xhr.open("GET", "/some/cool/url");
      xhr.send();

      expect(doneFn).not.toHaveBeenCalled();

      jasmine.Ajax.requests.mostRecent().respondWith({
        "status": 200,
        "responseText": 'in spec response'
      });

      expect(doneFn).toHaveBeenCalledWith('in spec response');
    });
  });

只有在使用respondWith时才会发送响应。只需下载文件,并将其作为src添加到您的SpecRunner.html中。示例用法请参见https://github.com/serv-inc/JSGuardian(请查看测试文件夹)。


jasmine-ajax 万岁 — 把这个 demo 加入到我的测试用例中:https://github.com/piecioshka/test-angular-services-testing/blob/master/src/app/photos.service.spec.ts#L84 - piecioshka

-1
根据您下面代码的传真,您很可能能够注入console.log()以获取状态码和状态文本。这将帮助您识别任何http错误。我猜测状态将返回404。
submit : function() {
    var url = window.arguments[0];
    var request = new XMLHttpRequest();
    request.open("POST", 'http://'+this.host+'/doSomething', true);
    request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    request.send("param="+param+"&emotions="+this.getParams());
    request.onreadystatechange = function() {
        console.log(this.status+ " - "+ this.statusText);
    };

}

另一种方法是查看Firebug控制台中的请求头/响应。这是一个好建议:如果您没有使用Firebug或Chrome开发工具,您应该将console.log()调用更改为将字符串附加到文档对象不要使用alert()调用。

如何使用Jasmine验证jQuery AJAX事件?。实现Jasmine的类似答案。


我不熟悉Jasmine,但我已经在我的答案中添加了一个链接,指向一个类似的线程的答案,看起来是你正在寻找的Jasmine测试。 - CBusBus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接