New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not compatable with SWHttpTrafficRecorder #232
Comments
Thanks for the issue. It has been tested… but separately, as you usually don't both stub and record what you stub, but rather record first and stub later. But you're right in that it should be mentioned in the README that you should not use both at the same time but rather one after the other, so the README should be more clear about that. |
So the reason I have a two in one is that I try to automate everything. I attempt to record, if the file name for the request doesn't exist then I do record the request, otherwise if it does exist I stub the request based off of the file. This requires me to register both. |
I see. I think you should still be able to register |
I thought that only one |
No you can register as many as you want. Let me find a Mac in a minute so I can give you an example |
Ok, so, basically my proposed solution is for you to call You can find this method's implementation here. As you can see, this method doesn't replace the supported This insertion is automatically done on the two If you use
So, now that I've had time to re-read the implementation of both pods, I don't see why this wouldn't work:
import Foundation
// Start with the default configuration
let config = URLSessionConfiguration.default
// If you indeed have the `OHHTTPStubs/NSURLSession` subspec listed in your `Podfile.lock`
// then OHHTTPStubs should have automatically injected its own `NSURLProtocol` at this point
// You can check this using some NSLog:
NSLog("protocol classes after OHHTTPStubs: \(config.protocolClasses)") // this should contain `OHHTTPStubsProtocol` among others
do {
// not sure about the translation of SWHttpTrafficRecorder API in Swift here, I'll let you adapt
let started = try SWHttpTrafficRecorder.sharedRecorder().startRecording(path:nil, forSessionConfiguration:config)
// At this point, SWHttpTrafficRecord should itself have added its own NSURLProtocol to the
// protocolClasses array, intercepting the traffic first, BEFORE anybody else (including OHHTTPStubs)
NSLog("Started: \(started)")
NSLog("protocolClasses after SWHTR: \(config.protocolClasses)")
} catch {
NSLog("Error while trying to start SWHttpTrafficRecorder")
}
// At this point, SWHttpTrafficRecorder is listed first in the protocolClasses array
// then OHHTTPStubs is next in line. This means that SWHTR will intercept requests first, then
// OHHTTPStubs will be given the ability to stub them next, then if the request passed thru both
// the request will finally hit the real world.
// If you want to make `OHHTTPStubs` intercept the requests BEFORE SWHttpTrafficRecorder
// Then you have to ask `OHHTTPStubs` to remove itself then re-insert itself at index 0
OHHTTPStubs.setEnabled(false, forSessionConfiguration: config) // remove first
OHHTTPStubs.setEnabled(true, forSessionConfiguration: config) // then reinsert, at index 0
// And ONLY then, create your NSURLSession, because if you create it before
// setting up the NSURLSessionConfiguration, changes in the configuration won't do anything
let session = URLSession(configuration: config)
let task = session.dataTask(with: yourURLHere)
task.resume() |
What's the difference between adding the protocol like so:
and like so:
If I register the class for NSURLProtocol does it register it for the default protocol, so any call to URLSessionConfiguration.default after adding a protocol will include the new protocol? |
The difference is that one applies to global sessions/connections, the other to sessions built with a given session configuration.
For more info, see:
For in-depth understanding, you can also find detailed information in Apple's API documentation on |
Alright maybe I'm confused here but something doesn't seem right. I was assuming that the setEnabled method is what was registering the class under the default session configuration, which is what AFNetworking was using. But after some testing I don't know if this is the case, how are you making it so that you stub AFNetworking requests? The reason I don't think it's the registerClass function is because SWHttpTrafficRecorder uses that to register its own protocol class but when I do:
the before and after are the same: before: Optional([OHHTTPStubsProtocol, _NSURLHTTPProtocol, _NSURLDataProtocol, _NSURLFTPProtocol, _NSURLFileProtocol, NSAboutURLProtocol]) As you can see, OHHTTPStubsProtocol is being registered but my custom protocol isn't listed. How is OHHTTPStubs making it so that the class is being registered with AFNetworking? You mentioned method swizzling but can you point me to where to start looking to see how this is happening? The session manager I'm using is an AFHTTPSessionManager and I pass it the default configuration: [NSURLSessionConfiguration defaultConfiguration]; I make sure to setup the session configuration after I've added the protocol classes, so that isn't the issue either. I'm using swift and objc interchangeably because my project has both and the code snippets come from different files. |
Alright so I took a look at OHHTTPStubs+NSURLSessionConfiguration and see where the method swizzling is happening. Now I understand my error. I was thinking that the URLProtocol RegisterClass was what was adding OHHTTPStubs to the session configuration but this isn't the case, it's being 'swizzled' in. Thanks for pointing that out in your comment, it took me a couple of reads through to understand exactly what you meant and I also had to read through the implementation and on method swizzling. Here's the post I read if anyone else that stumbles upon this is as confused as I was: |
Yup that's it. Again, it's explained explicitly here ("Automatic Loading" paragraph) in the README as pointed out before. |
Yea I read through that a bunch of times actually but since I'm a bit of a noob I didn't understand exactly what you meant by swizzling. I thought that the registerclass was what was swizzling the method because I didn't understand the concept of swizzling. I think all the new terminology threw me off too so I was confused when reading through the readme. Again I really appreciate the help! |
Ah right. Maybe we should put that NSHipster's link next to the "swizzling" mention in the README then. |
Maybe that and mentioning where you're swizzling the sessions, what really did it for me is actually seeing where you guys swizzled the config. |
I wanted to point out that this pod isn't compatible with the SWHttpTrafficRecorder as it points out on the readme. Both this pod and that pod try to register their own versions of NSURLProtocol which means one of them is going to lose, so either you don't record the file or you don't stub the response. I spent a good chunk of time trying to figure out why they weren't working together and thought this should be noted on your readme, as it makes it look like it's been tested and it should work when in reality it doesn't.
The text was updated successfully, but these errors were encountered: