2012-10-30 25 views
55

Tôi đã có một chức năng khá đơn giản mà trả về một .ajax jQuery() hứa hẹn như vậy:Làm thế nào để kiểm tra đơn vị đúng cách .jax() hứa hẹn sử dụng Jasmine và/hoặc Sinon?

CLAW.controls.validateLocation = function(val, $inputEl) { 
    return $.ajax({ 
     url: locationServiceUrl + 'ValidateLocation/', 
     data: { 
      'locationName': val 
     }, 
     beforeSend: function() { 
      $inputEl.addClass('busy'); 
     } 
    }).done(function(result) { 
     // some success clauses 
    }).fail(function(result) { 
     // some failure clauses 
    }).always(function() { 
     // some always clauses 
    }); 
} 

Đối với hầu hết các phần, giao diện lời hứa mới này hoạt động giống như một giấc mơ, và loại bỏ kim tự tháp callback khi sử dụng jQuery .ajax() là rất tốt. Tuy nhiên, tôi không thể cho cuộc đời của tôi tìm ra cách để kiểm tra đúng những lời hứa sử dụng Jasmine và/hoặc Sinon:

  1. Tất cả các tài liệu Sinon của giả sử bạn đang sử dụng cũ-trường callbacks; Tôi không thấy một ví dụ duy nhất làm thế nào để sử dụng nó với lời hứa/deferreds

  2. Khi cố gắng sử dụng một Jasmine hoặc Sinon do thám để do thám $ .ajax, các gián điệp là một cách hiệu quả ghi đè lên các lời hứa, vì vậy nó done, fail, và always khoản không còn tồn tại trên chức năng ajax, vì vậy lời hứa không bao giờ giải quyết và tung một lỗi thay vì

tôi thực sự chỉ yêu một hai làm thế nào để thử nghiệm những jQuery mới ví dụ hoặc .ajax() hứa hẹn với các libs kiểm tra nói trên. Tôi đã cọ xát 'mạng khá mãnh liệt và chưa thực sự nạo vét bất cứ điều gì khi làm như vậy. Một trong những tài nguyên tôi đã tìm thấy đề cập đến bằng cách sử dụng Jasmine.ajax, nhưng tôi muốn tránh rằng nếu có thể, nhìn thấy như Sinon cung cấp hầu hết các khả năng tương tự out-of-the-box.

Trả lời

105

Nó thực sự không phức tạp. Nó đủ để trả lời một lời hứa và giải quyết nó theo trường hợp của bạn.

Ví dụ:

spyOn($, 'ajax').andCallFake(function (req) { 
    var d = $.Deferred(); 
    d.resolve(data_you_expect); 
    return d.promise(); 
}); 

cho một thành công, hoặc

spyOn($, 'ajax').andCallFake(function (req) { 
    var d = $.Deferred(); 
    d.reject(fail_result); 
    return d.promise(); 
}); 

cho một thất bại.

Đối với Jasmine 2,0 cú pháp đã thay đổi một chút:

spyOn($, 'ajax').and.callFake(function (req) {}); 

phương pháp .andCallFake() không tồn tại trong Jasmine 2.0

+0

này làm việc tuyệt vời; Cảm ơn nhiều! –

+0

Không có vấn đề, một niềm vui;) – ggozad

+8

Bất kỳ ý tưởng cho cách Sinon? – lucke84

16

một cái gì đó dọc theo những dòng/với Sinon và jQuery deferreds

ajaxStub = sinon.stub($, "ajax"); 

function okResponse() { 
    var d = $.Deferred(); 
    d.resolve({ username: "testuser", userid: "userid", success: true }); 
    return d.promise(); 
}; 

function errorResponse() { 
var d = $.Deferred(); 
d.reject({},{},"could not complete"); 
return d.promise(); 
}; 

ajaxStub.returns(okResponse()); 
ajaxStub.returns(errorResponse()); 
+0

Bạn đã quên các cuộc gọi lại 'thành công' và' lỗi'. – Vanuan

0

Đây là cách tiếp cận đơn giản hơn chỉ với javascript.

quoteSnapshots: function (symbol, streamId) { 
       var FakeDeferred = function() { 
        this.error = function (fn) { 
         if (symbol.toLowerCase() === 'bad-symbol') { 
          fn({Error: 'test'}); 
         } 
         return this; 
        }; 
        this.data = function (fn) { 
         if (symbol.toLowerCase() !== 'bad-symbol') { 
          fn({}); 
         } 
         return this; 
        }; 
       }; 

       return new FakeDeferred(); 
      } 

Các câu lệnh if bên trong mỗi cuộc gọi lại là những gì tôi sử dụng trong bài kiểm tra để thực hiện thành công hoặc thực thi lỗi.

0

Giải pháp được đưa ra bởi @ggozad sẽ không hoạt động nếu bạn sử dụng những thứ như .complete().

Nhưng, hoan hô, hoa nhài làm một plugin để thực hiện chính xác này: http://jasmine.github.io/2.0/ajax.html

beforeEach(function() { 
    jasmine.Ajax.install(); 
}); 

afterEach(function() { 
    jasmine.Ajax.uninstall(); 
}); 

//in your tests 
expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url'); 
Các vấn đề liên quan