You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So this is a bug that has been haunting me for a few weeks now. And was the cause of me not running my service classes' specs unless I wasn't too lazy to recreate the cassettes.
Here's a snippet from my project that creates a get request with query parameters:
if let p = params where method == "GET" {
let charset = NSCharacterSet.URLQueryAllowedCharacterSet()
var query = ""
for key,value in p {
if let escapedValue = String(p[key]!).stringByAddingPercentEncodingWithAllowedCharacters(charset) {
query += "\(key)=\(escapedValue)&"
}
}
urlString += "?\(query)"
}
param is a [String : AnyObject] dictionary;
method is a string defining http verb
So this snippet constructs a query string and appends it to urlString variable that has the base url and resource path combined.
This urlString is then passed to NSURLRequest initializer that creates a request to perform with a session that holds a cassette.
And this is where the trouble comes in. DVR check's for presence of interaction in the cassette by looking at the request's URL. And by definition dictionary does not guarantee the order of the keys in which they will be passed in iteration.
If you have ["foo": 5, "bar" : true] the resulting query string can have two variations:
let query1 = "foo=5&bar=true&"
let query2 = "bar=true&foo=5&"
In the end they mean the same thing and will be interpreted correctly by the server, but the check will fail since query1 != query2.
I'm not sure how people construct requests in their code, but the solution can be achieved in two ways
make sure that query string key-values have deterministic order (e.g. alpahbetically a-z) and construct query string always in the same matter;
Add code in DVR interaction's check that ignores the query string when comparing URLs (split by ?) and compare the key values that are stored in the query string (reconstruct the dict by splitting by & and then by =).
If this project is still alive, I'd like to hear anyones thoughts.
The text was updated successfully, but these errors were encountered:
First off, creating NSURLs by hand using string manipulation is strongly discouraged. You should seriously considering switching to NSURLComponents and NSURLQueryItem. This would eliminate things being non-deterministic as well.
As far as why it's not matching, can you please provide a sample cassette and a sample test that isn't matching so we can debug it?
The problem with the test case is that it may pass sometimes because the query parameters will be constructed in the order that is stored in the cassette. But I will change my code to use NSURLComponents and NSURLQueryItem to see if this avoids the issue.
So this is a bug that has been haunting me for a few weeks now. And was the cause of me not running my service classes' specs unless I wasn't too lazy to recreate the cassettes.
Here's a snippet from my project that creates a get request with query parameters:
param
is a[String : AnyObject]
dictionary;method
is a string defining http verbSo this snippet constructs a query string and appends it to
urlString
variable that has the base url and resource path combined.This
urlString
is then passed toNSURLRequest
initializer that creates a request to perform with a session that holds a cassette.And this is where the trouble comes in. DVR check's for presence of interaction in the cassette by looking at the request's URL. And by definition dictionary does not guarantee the order of the keys in which they will be passed in iteration.
If you have
["foo": 5, "bar" : true]
the resulting query string can have two variations:let query1 = "foo=5&bar=true&"
let query2 = "bar=true&foo=5&"
In the end they mean the same thing and will be interpreted correctly by the server, but the check will fail since
query1 != query2
.I'm not sure how people construct requests in their code, but the solution can be achieved in two ways
?
) and compare the key values that are stored in the query string (reconstruct the dict by splitting by&
and then by=
).If this project is still alive, I'd like to hear anyones thoughts.
The text was updated successfully, but these errors were encountered: