Jasmine으로 jQuery AJAX 이벤트를 어떻게 확인합니까?


114

Jasmine을 사용하여 기본 jQuery AJAX 요청에 대한 BDD 사양을 작성하려고합니다. 현재 Jasmine을 독립 실행 형 모드 (예 :)로 사용하고 SpecRunner.html있습니다. jquery 및 기타 .js 파일을로드하도록 SpecRunner를 구성했습니다. 다음이 작동하지 않는 이유는 무엇입니까? has_returned는 "yuppi!" 경고가 잘 나타납니다.

describe("A jQuery ajax request should be able to fetch...", function() {

  it("an XML file from the filesystem", function() {
    $.ajax_get_xml_request = { has_returned : false };  
    // initiating the AJAX request
    $.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
             success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } }); 
    // waiting for has_returned to become true (timeout: 3s)
    waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
    // TODO: other tests might check size of XML file, whether it is valid XML
    expect($.ajax_get_xml_request.has_returned).toEqual(true);
  }); 

});

콜백이 호출되었는지 어떻게 테스트합니까? Jasmine을 사용한 비동기 jQuery 테스트와 관련된 블로그 / 자료에 대한 모든 포인터는 크게 감사 할 것입니다.

답변:


234

두 가지 유형의 테스트를 수행 할 수 있습니다.

  1. AJAX 요청을 위조하는 단위 테스트 (Jasmine의 스파이 사용) 통해 AJAX 요청 직전직후에 실행되는 모든 코드를 테스트 할 수 있습니다 . Jasmine을 사용하여 서버의 응답을 가짜로 만들 수도 있습니다. 실제 AJAX가 진행되지 않기 때문에 이러한 테스트는 더 빠르며 비동기 동작을 처리 할 필요가 없습니다.
  2. 실제 AJAX 요청을 수행하는 통합 테스트. 이것들은 비동기식이어야합니다.

Jasmine은 두 가지 테스트를 모두 수행하는 데 도움이 될 수 있습니다.

다음은 AJAX 요청을 위조 한 다음 위조 된 AJAX 요청이 올바른 URL로 이동하는지 확인하는 단위 테스트를 작성하는 방법에 대한 샘플입니다.

it("should make an AJAX request to the correct URL", function() {
    spyOn($, "ajax");
    getProduct(123);
    expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});

function getProduct(id) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    });
}

들어 2.0 재스민 사용하는 대신 :

expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");

이 답변 에서 언급했듯이

다음은 AJAX 요청이 성공적으로 완료되면 콜백이 실행되었는지 확인하는 유사한 단위 테스트입니다.

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    });
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    expect(callback).toHaveBeenCalled();
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: callback
    });
}

들어 2.0 재스민 사용하는 대신 :

spyOn($, "ajax").and.callFake(function(options) {

이 답변 에서 언급했듯이

마지막으로, 통합 목적을 위해 실제 AJAX 요청을 만드는 통합 테스트를 작성하고 싶다고 다른 곳에서 암시했습니다. 이것은 Jasmine의 비동기 기능인 waits (), waitsFor () 및 runs ()을 사용하여 수행 할 수 있습니다.

it("should make a real AJAX request", function () {
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    waitsFor(function() {
        return callback.callCount > 0;
    });
    runs(function() {
        expect(callback).toHaveBeenCalled();
    });
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "data.json",
        contentType: "application/json; charset=utf-8"
        dataType: "json",
        success: callback
    });
}

+1 알렉스 좋은 대답. 실제로 Deferred 개체를 사용하여 Test Ajax 요청을 열었던 유사한 문제에 직면했습니다 . 좀 봐 줄래? 감사.
Lorraine Bernard

12
귀하의 답변이 Jasmine의 공식 문서에 포함 되었으면합니다. 며칠 동안 나를 죽이는 문제에 대한 매우 명확한 대답.
Darren Newton

4
이 답변은이 질문에 대한 공식적인 답변으로 표시되어야합니다.
토마스 아마르

1
가장 최근의 통화 정보를 얻는 현재 방법은 $ .ajax.calls.mostRecent ()
camiblanch

1
일반 JS ajax에 대해 어떻게 구현 하시겠습니까?
Watchmaker

13

jasmine-ajax 프로젝트를보십시오 : http://github.com/pivotal/jasmine-ajax .

요청이 절대 나가지 않도록 XHR 계층에서 (jQuery 또는 Prototype.js의 경우) 스텁하는 드롭 인 도우미입니다. 그런 다음 요청에 대해 원하는 모든 것을 기대할 수 있습니다.

그런 다음 모든 케이스에 대한 고정 응답을 제공 한 다음 성공, 실패, 승인되지 않은 등 원하는 각 응답에 대한 테스트를 작성할 수 있습니다.

비동기 테스트 영역에서 Ajax 호출을 가져와 실제 응답 핸들러가 작동하는 방식을 테스트 할 수있는 많은 유연성을 제공합니다.


@jasminebdd에게 감사드립니다. jasmine-ajax 프로젝트는 내 js 코드를 테스트하는 방법처럼 보입니다. 그러나 연결 / 통합 테스트와 같이 서버에 대한 실제 요청으로 테스트하려면 어떻게해야합니까?
mnacos 2011 년

2
@mnacos jasmine-ajax는 특히 서버에 대한 호출을 피하려는 경우 단위 테스트에 주로 유용합니다. 통합 테스트를 수행하는 경우 이것은 아마도 원하는 것이 아니며 별도의 테스트 전략으로 설계되어야합니다.
Sebastien Martin

7

다음은 이와 같은 앱 js에 대한 간단한 예제 테스트 모음입니다.

var app = {
               fire: function(url, sfn, efn) {
                   $.ajax({
                       url:url,
                       success:sfn,
                       error:efn
                   });
                }
         };

URL 정규 표현식을 기반으로 콜백을 호출하는 샘플 테스트 스위트

describe("ajax calls returns", function() {
 var successFn, errorFn;
 beforeEach(function () {
    successFn = jasmine.createSpy("successFn");
    errorFn = jasmine.createSpy("errorFn");
    jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
      function (options) {
          if(/.*success.*/.test(options.url)) {
              options.success();
          } else {
              options.error();
          }
      }
    );
 });

 it("success", function () {
     app.fire("success/url", successFn, errorFn);
     expect(successFn).toHaveBeenCalled();
 });

 it("error response", function () {
     app.fire("error/url", successFn, errorFn);
     expect(errorFn).toHaveBeenCalled();
 });
});

고마워 친구. 이 예는 저에게 많은 도움이되었습니다! Jasmine> 2.0을 사용하는 경우 andCallFake의 구문은 spyOn (jQuery, "ajax"). and.callFake (/ * your function * /);
João Paulo Motta 2015 년

확실하지이 버전 문제입니다하지만 난에 오류가있어 경우에 .andCallFake사용 .and.callFake하는 대신합니다. 감사.
OO

5

Jasmine으로 ajax 코드를 지정할 때 의존하는 함수가 원격 호출을 시작하는 모든 것을 감시하여 문제를 해결합니다 (예 : $ .get 또는 $ ajax). 그런 다음 설정된 콜백을 검색하고 개별적으로 테스트합니다.

최근에 제가 제안한 예는 다음과 같습니다.

https://gist.github.com/946704


0

jqueryspy.com을 사용해보십시오. 테스트를 설명하는 구문과 같은 우아한 jquery를 제공하고 ajax가 완료된 후 콜백을 테스트 할 수 있습니다. 통합 테스트에 적합하며 최대 아약스 대기 시간을 초 또는 밀리 초 단위로 구성 할 수 있습니다.


0

Jasmine이 현재 버전 2.4이고 버전 2.0에서 몇 가지 기능이 변경되었으므로 더 최신 답변을 제공해야한다고 생각합니다.

따라서 AJAX 요청 내에서 콜백 함수가 호출되었는지 확인하려면 스파이를 만들고 callFake 함수를 추가 한 다음 스파이를 콜백 함수로 사용해야합니다. 방법은 다음과 같습니다.

describe("when you make a jQuery AJAX request", function()
{
    it("should get the content of an XML file", function(done)
    {
        var success = jasmine.createSpy('success');
        var error = jasmine.createSpy('error');

        success.and.callFake(function(xml_content)
        {
            expect(success).toHaveBeenCalled();

            // you can even do more tests with xml_content which is
            // the data returned by the success function of your AJAX call

            done(); // we're done, Jasmine can run the specs now
        });

        error.and.callFake(function()
        {
            // this will fail since success has not been called
            expect(success).toHaveBeenCalled();

            // If you are happy about the fact that error has been called,
            // don't make it fail by using expect(error).toHaveBeenCalled();

            done(); // we're done
        });

        jQuery.ajax({
            type : "GET",
            url : "addressbook_files/addressbookxml.xml",
            dataType : "xml",
            success : success,
            error : error
        });
    });
});

AJAX가 오류를 반환하더라도 Jasmine이 가능한 한 빨리 사양을 실행할 수 있도록 성공 함수와 오류 함수에 대한 트릭을 수행했습니다.

오류 함수를 지정하지 않고 AJAX가 오류를 반환하면 Jasmine에서 오류가 발생할 때까지 5 초 (기본 시간 제한 간격)를 기다려야합니다 Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.. 다음과 같이 고유 한 시간 제한을 지정할 수도 있습니다.

it("should get the content of an XML file", function(done)
{
    // your code
},
10000); // 10 seconds
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.