How can I make $httpBackend insensitive to the order of URL query parameters?
Asked Answered
P

2

16

I am using the Angular.js $httpBackend to test some services that wrap $http calls (this is in ngMock, not ngMockE2E).

It seems that things like expect and when are sensitive to the order of URL query parameters. E.g. if I do $httpBackend.when('POST','/apiCall?X=1&Y=2').respond(/* ... */) or $httpBackend.expectPOST('/apiCall?X=1&Y=2'), I get URL mismatches if I have Y=2&X=1 in the URL instead of X=1&Y=2.

I want to write my tests in such a way that the service being tested will be free to change the order of URL query string parameters without breaking the tests. I haven't been able to find anything to solve this in the $httpBackend documentation. What's the right way to do this?

Paraphrastic answered 12/3, 2014 at 20:28 Comment(0)
W
9

angular will sort the keys of the params object used in conjunction with $http.

$http({
    url:"/myurl",
    method:"GET",
    params:{
       Y:1
       X:2
    }}); 

Angular will do the following effectively: Object.keys(myParams).sort() and append the keys in that order. which ends up being '/myurl?X=2&Y=1'

I would suggest consistently using query parameters not directly in the url, but instead in the parameter params: that angular will then process.

Another solution would be to use Regular Expressions in your tests, something like

$httpBackend.expectPOST(/\/myurl\?((X|Y)=\d{1,}&?){2}/) regexper

The fact that you can use RegExp's is really hard to spot since the documentation redesign, as the colors do not blend.

Windrow answered 12/3, 2014 at 21:51 Comment(3)
Thanks - using params when doing the $http call seems promising, so I'll upvote, though I'm still hoping for an elegant solution purely on the testing side (using regexes seems like overkill here, not to mention severely affecting the readability of the test...)Paraphrastic
Yeah, I agree Regex's are not fun to read or changeWindrow
Here's the relevant code that sorts the keys: github.com/angular/angular.js/blob/…Clash
S
7

you can use the $httpParamSerializer service to achieve this:

$httpParamSerializer({ param: 1, param2: 2 });

This will return you a matching stringified querystring matching angulars $http service with params.

Sinistrorse answered 24/7, 2015 at 13:23 Comment(1)
Awesome answer!Shirl

© 2022 - 2024 — McMap. All rights reserved.