11
$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();

Abhiram mishra
  • 1,597
  • 2
  • 14
  • 34
  • How is the get called in the code you are testing? – Gustav Aug 14 '15 at 07:01
  • updated the expectGet , is that what you are looking for ? – Abhiram mishra Aug 14 '15 at 07:06
  • 1
    It looks like you expect the get to have parameters, but it doesn't. Make sure that your test is set up in the way that when the application code calls the get, it does so with the expected parameters, ie. `{limit: 10, start: 1}` – Gustav Aug 14 '15 at 07:10

3 Answers3

23

(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, '{}');
Arno_Geismar
  • 2,296
  • 1
  • 15
  • 29
  • +1 Adds point to the questions, yes, but I care about the param, and basing on the param I will be responding to the request ( httpbackend ) – Abhiram mishra Aug 14 '15 at 09:57
13

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.

Community
  • 1
  • 1
vilsbole
  • 1,922
  • 1
  • 18
  • 22
  • Great. Just remember to `JSON.parse` the data argument if you need to access some properties – Aurelio Feb 23 '16 at 09:17
  • He is asking for expectGET to validate the params not whenGET to utilize the params. This doesn't answer the question. – Alex Pineda Jun 23 '16 at 14:53
3

arguments for

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

and

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

are different. They should be same.

atinder
  • 2,080
  • 13
  • 15
  • updated the expectGet , wrote it wrong. It still does not work – Abhiram mishra Aug 14 '15 at 07:13
  • i don't see it. your expectGET still has this extra `?limit=10&start=1` part – atinder Aug 14 '15 at 07:15
  • Well the extra part is the dynamic query which needs to be mapped with the whenGet part of it. I have updated the question – Abhiram mishra Aug 14 '15 at 07:21
  • 3
    you need to use regex, refer http://stackoverflow.com/questions/21169076/mock-httpbackend-regex-not-matched – atinder Aug 14 '15 at 07:25
  • Addition to @atinder answer , know I had the problem with $httpBackend.expectGET('/restpath/api/v1/books?limit=10&start=1'); , as my service was also running this request. When I commented I got the modified regex working – Abhiram mishra Aug 14 '15 at 07:38