-->

$httpBackend with request with query param

2019-06-15 08:27发布

问题:

$httpBackend.whenGET('/restpath/api/v1/books')
.respond({// some data}); 

I get the following error

Error: Unexpected request: GET /restpath/api/v1/books
 Expected GET /restpath/api/v1/books?limit=10&start=1

For the expectGET I have the following , and this creates dynamic query string. mostly the 'start' parameter, and the whenGET part, I am trying to server a dynamic content depending on the 'start'

$httpBackend.expectGET('/restpath/api/v1/books?limit=10&start=1'); // the actual service goes here , which does the $http service. we don't care $httpBackend.flush();

回答1:

(for angular apps with versions lower than v1.5.0-build.4371 )

If you dont care about the parameters after your '?' you can do this :

$httpBackend.expectGET(/.*?restpath\/api\/v1\/books?.*/g).respond(200, '{}');

if you care about the first param do this :

$httpBackend.expectGET(/.*?restpath\/api\/v1\/books?limit=10.*/g).respond(200, '{}');

if you care about them all do this :

$httpBackend.expectGET("/restpath/api/v1/books?limit=10&start=1").respond(200, '{}');


回答2:

EDIT

As of v1.5.0-build.4371 the docs state that the respond callback accepts a params argument.

By default, query parameters on request URLs are parsed into the params object. So a request URL of /list?q=searchstr&orderby=-name would set params to be {q: 'searchstr', orderby: '-name'}

So for '/restpath/api/v1/books?limit=10&start=1' you will get:

$httpBackend
   .whenGET('/restpath/api/v1/books?limit=10&start=1')
   .respond(function(method, url, data, headers, params) {

    // params will be {
    //   limit: 10,
    //   start: 1
    // }

   });

PREVIOUS

  1. You use

    • .expectGET() if you want to $httpBackend to throw an exception on mismatch.
    • .whenGET() in the other cases.
  2. The docs state that .respond() can accept either an Array or a callback function, with the signature: function(method, url, data, headers) {};

Now that we know how to access the request url, in order to serve a dynamic content, we can simply parse the url we receive in the .respond() callback using a helper function such as the one posted by Andy E in this question:

// inspired by Andy E
// @https://stackoverflow.com/users/94197/andy-e

function matchParams(query) {
   var match;
   var params = {};

   // replace addition symbol with a space
   var pl = /\+/g;

   // delimit params
   var search = /([^&=]+)=?([^&]*)/g;


   var decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); };

   while (match = search.exec(query))
     params[decode(match[1])] = decode(match[2]);

   return params;
}

With this helper in our scope, we can know build a dynamic response, such as:

// we use a regex to be able to still respond to 
// dynamic parameters in your request
var urlRegex = /\/restpath\/api\/v1\/books\?limit=(\d+)&start=(\d+)/;

$httpBackend
   .whenGET(urlRegex)
   .respond(function(method, url){

      // send only the url parameters to the helper
      var params = matchParams(url.split('?')[1]);

      // params is now an object containing
      // {limit: 10, start:1}
      // so do whatever you want with it.
      var dynamicData = getMockData(params.start);


      // don't forget to return.
      return [200, dynamicData];
   });

mySuperFactory.method().then(...);

// now resolve the Promise by flushing.
$httpBackend.flush();

And voila! You can serve dynamic mock data to your tests.



回答3:

arguments for

whenGET('/restpath/api/v1/')

and

expectGET('restpath/api/v1/books?limit=10&start=1')

are different. They should be same.