web-dev-qa-db-fra.com

Comment simuler la réponse jquery.ajax ()?

J'écris des tests QUnit pour un JavaScript qui fait AJAX appels.

Pour l'isolement, j'écrase $.ajax Pour écrire le tableau de paramètres d'un appel AJAX à une variable. Cela fonctionne pour tester comment les méthodes utilisent les fonctions AJAX , mais j'ai du mal à tester le gestionnaire de réussite de $.load()

De la documentation à http://api.jquery.com/load/ :

Lorsqu'une réponse réussie est détectée (c'est-à-dire lorsque textStatus est "succès" ou "non modifié"), .load () définit le contenu HTML de l'élément correspondant sur les données renvoyées.

J'ai donc tenté de renvoyer un objet contenant des objets portant le même nom que des variables pour le gestionnaire de réussite:

    //Mock ajax function
    $.ajax = function (param) {
        _mockAjaxOptions = param;
        var fakeAjaxSuccess = { responseText: "success", textStatus: "success", XMLHttpRequest: "success" };
        return fakeAjaxSuccess;
    };

Mais cette approche n'a pas fonctionné.

Comment puis-je reproduire le comportement d'un appel réussi AJAX?

37
StuperUser

Après une lecture inspirée de @Robusto et @Val, j'ai trouvé une méthode qui fonctionne:

//Mock ajax function
$.ajax = function (param) {
    _mockAjaxOptions = param;
    //call success handler
    param.complete("data", "textStatus", "jqXHR");
};

Au lieu de déclencher l'événement à partir d'un vrai code $ .ajax ou en déclenchant des événements, mon faux objet ajax appelle la fonction (qui est transmise en paramètre à $.ajax()) dans le cadre de ma fausse fonction .

14
StuperUser

Cette question a quelques années et pour les nouvelles versions de jQuery a un peu changé.

Pour ce faire avec Jasmin, vous pouvez essayer approche de Michael Falaga

Solution

  function ajax_response(response) {
    var deferred = $.Deferred().resolve(response);
    return deferred.promise();
  }

Avec Jasmine

  describe("Test test", function() {
    beforeEach(function() {
      spyOn($, 'ajax').and.returnValue(
        ajax_response([1, 2, 3])
      );
    });
    it("is it [1, 2, 3]", function() {
      var response;
      $.ajax('GET', 'some/url/i/fancy').done(function(data) {
        response = data;
      });
      expect(response).toEqual([1, 2, 3]);
    });
  });

Pas de jasmin

  $.ajax = ajax_response([1, 2, 3]);
  $.ajax('GET', 'some/url/i/fancy').done(function(data) {
     console.log(data); // [1, 2, 3]
  });
24
user1634074

Utilisez une fermeture pour remplacer $.ajax Par une réponse fictive

Après avoir essayé la réponse acceptée et la réponse publiée par user1634074 , j'ai conçu ce mélange simple et flexible des deux.

Dans sa forme la plus élémentaire…

function ajax_response(response) {
  return function (params) {
    params.success(response);
  };
}
$.ajax = ajax_response('{ "title": "My dummy JSON" }');

Dans l'exemple ci-dessus, définissez une fonction ajax_response() qui accepte une chaîne JSON comme argument (ou n'importe quel nombre d'arguments personnalisés utiles pour simuler une réponse) et renvoie une fonction de fermeture anonyme qui sera affectée à $.ajax Comme dérogation pour les tests unitaires.

La fonction anonyme accepte un argument params qui contiendra l'objet settings passé à la fonction $.ajax. Et il utilise les arguments passés à la fonction externe pour simuler une réponse du serveur. Dans cet exemple, il simule toujours une réponse réussie du serveur, en appelant simplement le rappel success et en lui fournissant le JSON factice.

Il est facile de reconfigurer…

function ajax_response(response, success) {
  return function (params) {
    if (success) {
      params.success(response);
    } else {
      params.error(response);
    }
  };
}

// Simulate success
$.ajax = ajax_response('{ "title": "My dummy JSON." }', true); 
doAsyncThing(); // Function that calls $.ajax

// Simulate error
$.ajax = ajax_response('{ "error": "Who is the dummy now?" }', false); 
doAsyncThing(); // Function that calls $.ajax

Ci-dessous, nous pouvons le voir en action…

/* FUNCTION THAT MAKES AJAX REQUEST */
function doAsyncThing() {
  $.ajax({
    type: "POST",
    url: "somefile.php",
    // data: {…},
    success: function (results) {
      var json = $.parseJSON(results),
          html = $('#ids').html();
      $('#ids').html(html + '<br />' + json.id);
    }
  });
}

/* BEGIN MOCK TEST */
// CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
function ajax_response(response) {
  return function (params) {
    params.success(response);
  };
}

var n = Prompt("Number of AJAX calls to make", 10);

for (var i = 1; i <= n; ++i) {
  
  // OVERRIDE $.ajax WITH DUMMY FUNCTION AND FAKE RESPONSE
  $.ajax = ajax_response('{ "id": ' + i + ' }');
  doAsyncThing();
}
/* END MOCK TEST */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="ids">IDs:</p>
11
gfullam

Mock $ .ajax au besoin sans déranger jQuery

Les réponses ici sont bonnes mais avaient un besoin spécifique de construire une fausse réponse à un seul appel d'API tout en laissant tous les autres appels d'API inchangés jusqu'à ce que le service backend soit construit afin que je puisse continuer à construire des choses sur l'interface utilisateur.

L'objet API utilise $ .ajax sous le capot afin que vous puissiez appeler une méthode API comme ceci:

api.products({ price: { $lt: 150, tags: ['nike', 'shoes'] } })
.done(function(json) {
  // do something with the data
})
.error(function(err) {
  // handle error
});

Cette méthode fait l'affaire:

function mockAjax(options) {
  var that = {
    done: function done(callback) {
      if (options.success)
        setTimeout(callback, options.timeout, options.response);
      return that;
    },
    error: function error(callback) {
      if (!options.success)
        setTimeout(callback, options.timeout, options.response);
      return that;
    }
  };
  return that;
}

Remplacez ensuite un seul appel API sans toucher $ .ajax:

api.products = function() {
  return mockAjax({
    success: true,
    timeout: 500,
    response: {
      results: [
        { upc: '123123', name: 'Jordans' },
        { upc: '4345345', name: 'Wind Walkers' }
      ]
    }
  });
};

https://jsfiddle.net/Lsf3ezaz/2/

4
Jason Sebring

Je pense que le lien ci-dessous devrait aider. quant à un paramètre je n'en suis pas si sûr mais ça pourrait l'être.

$.fn.ajax.success =  function (){
  ///the rest goest here
}

Remplacer la fonction jQuery .val ()?

1
Val

Regardez la documentation jQuery: vous verrez que la configuration Ajax fournit un certain nombre d'autres conditions qui sont testées. Si vous les faites tous pointer vers votre fakeAjaxSuccess, vous pourriez atteindre votre objectif.

Vous pouvez également envelopper votre $.ajax appelle dans sa propre fonction et pour tout appel, il suffit d'appeler votre gestionnaire d'événements avec l'objet fakeAjaxSuccess.

1
Robusto