Skip to content

Instantly share code, notes, and snippets.

@joemasilotti
Last active January 18, 2024 03:35
Show Gist options
  • Save joemasilotti/7ff31584c0b6981a8f41 to your computer and use it in GitHub Desktop.
Save joemasilotti/7ff31584c0b6981a8f41 to your computer and use it in GitHub Desktop.
Xcode UI Testing - How to mock network data

UI Testing - Mocking Network Data

  1. Create a Configuration object that provides an instance of NSURLSession. When running under UI Testing return a seeded one, otherwise use the default one.
  2. Grab a NSURLSession from the configuration in your HTTP client.
  3. Subclass NSURLSession to use seeded data when appropriate.
  4. Seed your response JSON in your UI Tests.
import Foundation
struct Config {
static let urlSession: NSURLSession = UITesting() ? SeededURLSession() : NSURLSession.defaultSession()
}
private func UITesting() -> Bool {
return NSProcessInfo.processInfo().arguments.contains("UI-TESTING")
}
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()
}
}
import Foundation
extension NSURLSession {
static func defaultSession() -> NSURLSession {
return NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
}
}
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)
}
}
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