$timeout
peut être espionné ou tourné en dérision, comme le montre l'exemple suivant cette réponse :
beforeEach(module('app', ($provide) => {
$provide.decorator('$timeout', ($delegate) => {
var timeoutSpy = jasmine.createSpy().and.returnValue($delegate);
// methods aren't copied automatically to spy
return angular.extend(timeoutSpy, $delegate);
});
}));
Il n'y a pas grand-chose à tester ici, puisque $timeout
est appelé avec une fonction anonyme. Pour des raisons de testabilité, il est logique de l'exposer en tant que méthode scope/controller :
$scope.submitFormHandler = function () {
$('#submitForm').click();
};
...
$timeout($scope.submitFormHandler, 2000);
Puis a espionné $timeout
peuvent être testés :
$timeout.and.stub(); // in case we want to test submitFormHandler separately
scope.submitRequest();
expect($timeout).toHaveBeenCalledWith(scope.submitFormHandler, 2000);
Et la logique à l'intérieur $scope.submitFormHandler
peut être testé de différentes manières.
Un autre problème est que jQuery ne fonctionne pas bien avec les tests unitaires et nécessite d'être testé contre le DOM réel (c'est l'une des nombreuses raisons pour lesquelles jQuery devrait être évité dans les applications AngularJS lorsque c'est possible). Il est possible d'espionner/mocker l'API jQuery comme le montre l'exemple suivant cette réponse .
$(...)
peut être espionnée :
var init = jQuery.prototype.init.bind(jQuery.prototype);
spyOn(jQuery.prototype, 'init').and.callFake(init);
Et on peut s'en moquer :
var clickSpy = jasmine.createSpy('click');
spyOn(jQuery.prototype, 'init').and.returnValue({ click: clickSpy });
Notez qu'il est prévu que la fonction simulée renvoie un objet jQuery pour l'enchaînement avec click
méthode.
Quand $(...)
est simulé, le test n'exige pas que l'option #submitForm
à créer dans le DOM, c'est la méthode préférée pour les tests unitaires isolés.