2012-08-22 41 views
7

在這個jsFiddle中可以看到,我有一個函數'init'來配置一個按鈕,當點擊它時會打開一個進度對話框併發出一個Ajax調用。我想單元測試(使用QUnit)這段JavaScript代碼,並檢查以下情況:我該如何測試這個JavaScript函數,包括模擬Ajax調用?

  1. Ajax調用成功

我需要模擬出至少Ajax調用

  • Ajax調用失敗並致電window.open,其他調用我確定,取決於單元測試的實現。

    如何爲測試這兩種方案的代碼編寫QUnit單元測試?

    編輯:需要進行測試的代碼:

    所有,下載的
    var statusmod = (function() { 
        var spinner = $("#spinner"); 
    
        var init = function(id) { 
         var progressDialog = $("#progressdialog-content").dialog({ 
          autoOpen: false, 
          title: "Launching Status Page" 
         }); 
         var errorDialog = $("#errordialog-content").dialog({ 
          autoOpen: false, 
          modal: true, 
          buttons: { 
           "OK": function() { 
            $(this).dialog("close"); 
           } 
          } 
         }); 
    
         var btn = $("#button-status"); 
         btn.button().click(function() { 
          spinner.show(); 
    
          progressDialog.dialog("open"); 
    
          var url = $.validator.format("/api/binid/?id={0}", id); 
          // Call Web service to get binary ID 
          $.ajax({ 
           url: url, 
           dataType: "json" 
          }).done(function(data) { 
           window.open($.validator.format("http://status/?Page=Status&Id={0}", data.Id), target = "_newtab"); 
          }).fail(function(jqXHR, msg, errorThrown) { 
           errorDialog.dialog("open"); 
          }).always(function() { 
           progressDialog.dialog("close"); 
          }); 
    
          return false; 
         }); 
        }; 
    
        return { 
         init: init, 
         _spinner: spinner 
        }; 
    }()); 
    
  • +1

    考慮的嘲諷Ajax調用mockjax,就像一個魅力 – rsplak

    +0

    @rsplak能否請你展示如何運行測試Ajax的回調已被調用後?目前看不到如何。 – aknuds1

    回答

    1

    我已成功爲成功案例和失敗案例編寫了一個QUnit測試,您可以從this jsFiddle中看到。我僱用了Mockjax來僞造Ajax響應並模擬成功/失敗條件。值得注意的是,我將Ajax調用配置爲同步的,以便我可以編寫同步測試,因爲在異步Ajax回調啓動後,我無法確定如何運行測試。

    我還利用Sinon.JS庫來僞造依賴關係,並驗證例如對話框正確啓動。

    工作測試代碼包含在下面,請參閱我的問題的測試功能(statusmod.init)。如果您認爲我遺漏了某些內容,請告訴我。

    var dialogSpy = null; 
    var windowSpy = null; 
    var id = "srcId"; 
    var binId = "binId"; 
    var url = $.validator.format("/api/binid/?id={0}", id); 
    var btnId = "#button-status"; 
    
    module("Open status page", { 
        setup: function() { 
         // Allow us to run tests synchronously 
         $.ajaxSetup({ 
          async: false 
         }); 
         windowSpy = sinon.spy(window, "open"); 
         dialogSpy = sinon.spy(); 
         sinon.stub($.fn, "dialog", function() { 
          return { 
           "dialog": dialogSpy 
          }; 
         }); 
    
         statusmod.init(id); 
        }, 
        teardown: function() { 
         windowSpy.restore(); 
         $.fn.dialog.restore(); 
         $.mockjaxClear(); 
         // Remove click event handler for each test 
         $(btnId).unbind(); 
        } 
    }); 
    
    test("Successfully open status page", function() { 
        expect(4); 
    
        $.mockjax({ 
         url: url, 
         contentType: "text/json", 
         responseText: { 
          Id: binId 
         } 
        }); 
    
        var spinner = statusmod._spinner; 
        var spinnerSpy = sinon.spy(spinner, "show"); 
    
        $(btnId).click(); 
    
        ok(spinnerSpy.calledOnce, "Spinner shown"); 
        ok(dialogSpy.withArgs("open").calledOnce, "Dialog opened"); 
        ok(dialogSpy.withArgs("close").calledOnce, "Dialog closed"); 
        equal(windowSpy.lastCall.args[0], $.validator.format("http://status/?Page=Status&Id={0}", binId), "Window opened"); 
    }); 
    
    test("Binary ID not found on server", function() { 
        expect(3); 
    
        $.mockjax({ 
         url: url, 
         contentType: "text/json", 
         status: 404 
        }); 
    
        $(btnId).click(); 
    
        ok(dialogSpy.withArgs("open").calledTwice, "Dialogs opened"); 
        ok(dialogSpy.withArgs("close").calledOnce, "Progress dialog closed"); 
        ok(!windowSpy.called, "Window not launched"); 
    }); 
    
    0

    第一,包括Mockjax

    然後嘲笑你的Ajax調用:

    module("Mock Ajax", { 
        setup: function() { 
        /** this mocks the ajax call **/ 
        $.mockjax({ 
         url: 'yourUrl.php', 
         data: {'action': 'your', 
         'data': { 
          'that': 'you', 
          'send': 'here' 
         } 
         }, 
         responseText:'{"your": ["returned":"json"],"string"}' 
        }); 
        }); 
    }); 
    

    然後你就可以讓你的Ajax調用的測試用例:

    test("Your testcase", function() { 
        $.ajax('yourUrl.php', 
        data: {'action': 'your', 
         'data': { 
         'that': 'you', 
         'send': 'here' 
        } 
        }, function(data) { 
         ok("do something with your data"); 
        }); 
    }); 
    

    的Et瞧,你已經成功地測試了什麼!你可以添加額外的參數給你的mockjax調用(isTImeout,isError等)。文檔可以找到here

    這些是基礎知識,您可以使用相當完整的文檔來編輯它以滿足您的需求。

    +0

    謝謝,但這並不能真正解決我的問題。我不想在我的測試用例中進行模擬Ajax調用,我想調用'status.init',單擊按鈕並確保正確調用Ajax調用,並確保完成/失敗/始終回調正確事情。我現在有一個幾乎可以解決這個問題的解決方案,但是我目前正停留在mockjax的一個小細節上。 – aknuds1

    +0

    在那個筆記上,也許你可以回答我特定的mockjax問題,因爲它應該很簡單? http://stackoverflow.com/questions/12093731/why-does-mockjax-return-an-altered-response-to-my-ajax-consumer – aknuds1

    相關問題