- Create a
Configuration
object that provides an instance ofNSURLSession
. When running under UI Testing return a seeded one, otherwise use the default one. - Grab a
NSURLSession
from the configuration in your HTTP client. - Subclass
NSURLSession
to use seeded data when appropriate. - Seed your response JSON in your UI Tests.
Last active
January 18, 2024 03:35
-
-
Save joemasilotti/7ff31584c0b6981a8f41 to your computer and use it in GitHub Desktop.
Xcode UI Testing - How to mock network data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct Config { | |
static let urlSession: NSURLSession = UITesting() ? SeededURLSession() : NSURLSession.defaultSession() | |
} | |
private func UITesting() -> Bool { | |
return NSProcessInfo.processInfo().arguments.contains("UI-TESTING") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
typealias HTTPResult = (NSData?, ErrorType?) -> Void | |
class HTTPClient { | |
private let session: NSURLSession | |
init(session: NSURLSession = Config.urlSession) { | |
self.session = session | |
} | |
func get(url: NSURL, completion: HTTPResult) { | |
let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in | |
// ... // | |
} | |
task.resume() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension NSURLSession { | |
static func defaultSession() -> NSURLSession { | |
return NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), | |
delegate: nil, delegateQueue: NSOperationQueue.mainQueue()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
typealias DataCompletion = (NSData?, NSURLResponse?, NSError?) -> Void | |
class SeededURLSession: NSURLSession { | |
override func dataTaskWithURL(url: NSURL, completionHandler: DataCompletion) -> NSURLSessionDataTask { | |
return SeededDataTask(url: url, completion: completionHandler) | |
} | |
} | |
class SeededDataTask: NSURLSessionDataTask { | |
private let url: NSURL | |
private let completion: DataCompletion | |
private let realSession = NSURLSession.defaultSession() | |
init(url: NSURL, completion: DataCompletion) { | |
self.url = url | |
self.completion = completion | |
} | |
override func resume() { | |
guard let json = NSProcessInfo.processInfo().environment[url.absoluteString] | |
else { realSession.dataTaskWithURL(url, completionHandler: completion); return } | |
let response = NSHTTPURLResponse(URL: url, statusCode: 200, HTTPVersion: nil, headerFields: nil) | |
let data = json.dataUsingEncoding(NSUTF8StringEncoding) | |
completion(data, response, nil) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
class UITests: XCTestCase { | |
let app = XCUIApplication() | |
let postCount = "33" | |
override func setUp() { | |
super.setUp() | |
continueAfterFailure = false | |
app.launchArguments += ["UI-TESTING"] | |
app.launchEnvironment["http://masilotti.com/api/posts.json"] = "{\"posts\": \(postCount)}" | |
app.launch() | |
} | |
func test_DisplaysPostCount() { | |
let postCountLabel = app.staticTexts[postCount] | |
waitForElementToAppear(postCountLabel) | |
} | |
private func waitForElementToAppear(element: XCUIElement, file: String = __FILE__, line: UInt = __LINE__) { | |
let existsPredicate = NSPredicate(format: "exists == true") | |
expectationForPredicate(existsPredicate, evaluatedWithObject: element, handler: nil) | |
waitForExpectationsWithTimeout(5) { (error) -> Void in | |
if (error != nil) { | |
let message = "Failed to find \(element) after 5 seconds." | |
self.recordFailureWithDescription(message, inFile: file, atLine: line, expected: true) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment