2010-07-06 5 views
1

je vais avoir une fonction javascript en utilisant jquery:faire javascript rappel-ish fonction

my.namespace.loadSomeStuff = function() { 

    $.get('/Services/loadStuff', function(c){ 
     $("#stuffDiv").html(c); 
    }); 
}; 

et essaie d'écrire des tests unitaires pour cela.

maintenant, puisque cette fonction ne retourne vraiment rien et en chargeant certains trucs asynchrones en utilisant 'get' de jquery j'ai du mal à tester ça.

essentiellement ce que je voudrais faire est d'appeler cette fonction, attendez jusqu'à ce qu'il retourne quelque chose, puis accéder aux éléments chargés de vérifier ... quelque chose comme:

my.namespace.loadSomeStuff(function(){ 
    alert('boo'); 
    assertSame('Login', $("#stuffDiv").find(......); 
}); 

maintenant, je créé un en le modèle qui appelle le test unitaire, et il va charger et afficher correctement, mais l'alerte ou l'assertion ne sont jamais exécutées.

est-il un moyen que je peux faire cela sans ajouter une tonne de code supplémentaire pour chaque fonction que j'ai?

grâce t

Répondre

1

Il faudrait ajouter un argument à la méthode loadSomeStuff pour recevoir la fonction de rappel que vous avez appelé dans votre exemple de code, puis appelez délibérément:

my.namespace.loadSomeStuff= function(callback) { 
    $.get('/Services/loadStuff', function(c){ 
     $("#stuffDiv").html(c); 
     if (callback!==undefined) 
      callback(); 
    }); 
}; 

Je ne suis pas sûr qu'il vaut la peine de rendre votre code plus compliqué simplement pour soutenir les tests unitaires, bien que vous pourrait argumenter que l'ajout de rappels aux fonctions asynchrones est d'une utilité générale.

Une alternative serait que le test utilise un délai brut.

Vous pouvez utiliser ajaxSuccess comme mentionné par Nick (peut-être combiné avec un délai d'attente, et/ou attraper ajaxError?). Mais il me semble que cela pourrait ajouter un peu trop de connaissances sur la mise en œuvre pour un test unitaire. Que se passe-t-il si loadSomeStuff est modifié à l'avenir pour fonctionner sans XMLHttpRequest, ou peut-être seulement l'utiliser parfois, quand il n'est pas mis en cache? Ensuite, le test unitaire va se casser. Bien sûr, vous pouvez mettre à jour le test pour qu'il corresponde à la mise en œuvre, mais ce n'est pas vraiment un test unitaire utile, n'est-ce pas?

+0

ce que me dit que « le rappel n'est pas une fonction » est-il une autre façon que je dois invoquer cette fonction maintenant? –

+0

Ah, oui, vous auriez besoin d'une vérification qu'un 'callback' a effectivement été passé, sinon le code qui ne fournissait pas de callback échouerait maintenant! Ajouté dans l'exemple de code ci-dessus. – bobince

1

Vous pouvez utiliser the global AJAX events for this, par exemple:

$(document).ajaxSuccess(function() { 
    assertSame('Login', $("#stuffDiv").find(......)); 
}); 

ajaxSuccess se passerait-il après chaque requête AJAX, si vous voulez un événement qui a couru après toutes les demandes simultanées ont terminé, puis ajaxStop est ce que vous cherchez. Ces deux gestionnaires n'ont pas besoin d'être attachés directement à your AJAX methods, ils peuvent être fait dans les tests unitaires.

Ce sont des événements normaux (full list here), de sorte que vous pouvez .bind()/.unbind() selon les besoins, par exemple lorsque le test unitaire ci-dessus est fait:

$(document).ajaxSuccess(function() { 
    assertSame('Login', $("#stuffDiv").find(......)); 
    $(this).unbind('ajaxSuccess'); //cleanup 
});