can not match on query parameters listed in the requests.get param keyword
Bug #1675133 reported by
Mary Bucknell
This bug affects 1 person
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
requests-mock |
New
|
Undecided
|
Unassigned |
Bug Description
I would like to be able to set up different mock responses based on the query parameters. The code that I'm testing using the params keyword to pass the query parameter to the requests.get. If I include the query parameters in the string to be matched, the matching does not occur.
It would also be great if the request_history would include the query parameters specified using the keyword param.
To post a comment you must log in.
Hi, Thanks for the report.
So there is definitely a way to set up responses based on query paramters but at the moment they are included in the url string, however there are some edge cases to it that boil down to the fact that query strings are not matched by default and the last defined matcher has priority.
So working through an example:
with requests_ mock.mock( ) as m: site.example. com", text='2') site.example. com?a=b", text='1')
m.get("http://
m.get("http://
print requests.get('http:// site.example. com?a=b' ).text site.example. com?a=c' ).text
print requests.get('http://
Will print as expected 1 then 2, however if i invert the order the mocks are defined in you'll get 2, 2 because the 2 matcher is handling both query strings first. Notice that 2 is triggered even though a=c is not defined anywhere. This can be unfortunate but it made testing urls with queries like filter or sort order commands easier because it typically doesn't significantly change the response from the url in testing.
To compensate for this there is a flag called complete_qs which you can set that will make it so the response will only match if the query string is matched exactly. So changing the example above:
with requests_ mock.mock( ) as m: site.example. com?a=b", text='1', complete_qs=True) site.example. com", text='2', complete_qs=True)
m.get("http://
m.get("http://
print requests.get('http:// site.example. com?a=b' ).text site.example. com?a=c' ).text
print requests.get('http://
notice i have added complete_qs AND i have changed the order they are defined in so that the more general matcher now is defined last (has priority) which would have failed above.
With this setup I get '1' and then a NoMockAddress exception because both matchers will only be triggered when the query string is an exact match.
I'm guessing that you are running into some combination of those problems when defining your responses that looks like you are not matching at all.
So i understand the ordering problem is non-intuitive and should probably be better documented, however do you think it would be better to allow defining query strings like get(url, query={'a', ['b']}) or something? that would be a fairly easy thing to support if it was confusing i would just need to look at what interface requests uses for that and emulate it.
Regarding request_history, that information is present i just call it qs, so printing:
print m.last_request.qs
above would give me:
{'a': ['b']}
Is that what you are looking for? I don't remember if the `qs` name was something i made up or something standard, are you suggesting we alias it to `keyword`?
Let me know if that helps and suggestions for the interface. I'm pretty sure the functionality you need is there it just might be intuitive enough.