2012-08-22 8 views
7

Come visto in questo jsFiddle, ho una funzione 'init' che configura un pulsante in modo che quando viene cliccato apre una finestra di dialogo di avanzamento ed emette una chiamata Ajax. Voglio unit test questo codice JavaScript (usando QUnit), e verificare i seguenti casi:Come posso testare questa funzione JavaScript, incluso il mocking della chiamata Ajax?

  1. Ajax chiamata riesce
  2. Ajax chiamata non riesce

ho bisogno di prendere in giro fuori almeno la chiamata Ajax e la chiamata a window.open e altre chiamate sono sicuro, a seconda dell'implementazione del test dell'unità.

Come posso scrivere i test di unità QUnit per il mio codice che testa questi due scenari?

EDIT: Il codice che deve essere testato:

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

consideri mockjax per beffardo la chiamata ajax, funziona come un fascino – rsplak

+0

@rsplak La prego di mostrare come eseguire i test dopo i callback Ajax sono state invocate? Non riesco a vedere come, al momento. – aknuds1

risposta

1

Ho scritto con successo un test QUnit per il caso di successo e un altro per il caso di errore, come potete vedere da this jsFiddle. Ho impiegato Mockjax per simulare le risposte Ajax e simulare le condizioni di successo/fallimento. In particolare, ho configurato le chiamate Ajax per essere sincrone, in modo da poter scrivere test sincroni, poiché avevo difficoltà a capire come eseguire i miei test dopo che erano stati attivati ​​i callback Ajax asincroni.

Io uso anche la libreria Sinon.JS per falsificare le dipendenze e verificare che ad es. le finestre di dialogo vengono avviate correttamente.

Il codice di prova di lavoro è incluso di seguito, vedere la mia domanda per la funzione in prova (statusmod.init). Fammi sapere se c'è qualcosa che pensi di aver omesso.

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

Prima di tutto, scaricare e comprendono Mockjax.

Poi deridere le chiamate 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"}' 
    }); 
    }); 
}); 

e quindi è possibile effettuare la chiamata ajax in un TestCase:

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

Et voilà, hai testato con successo qualcosa! Puoi aggiungere parametri extra alla tua chiamata a mockjax (isTImeout, isError, ecc.). La documentazione può essere trovata here.

Queste sono le basi, è possibile modificarlo in base alle proprie esigenze utilizzando la documentazione, che è piuttosto completa.

+0

Grazie, ma questo non risolve il mio problema. Non voglio fare una finta chiamata Ajax nel mio testcase, voglio chiamare 'status.init', fare clic sul pulsante, e assicurarmi che la chiamata Ajax venga eseguita correttamente e che i callback fatti/falliti/sempre facciano il giusto cosa. Ho una soluzione quasi funzionante da hackerare il problema oggi, ma al momento sono bloccato in un piccolo dettaglio in mockjax. – aknuds1

+0

Su quella nota, forse puoi rispondere alla mia specifica domanda di mockjax come dovrebbe essere abbastanza semplice? http://stackoverflow.com/questions/12093731/why-does-mockjax-return-an-altered-response-to-my-ajax-consumer – aknuds1