From bfef81c78e1e95e20a9a3336a9dc5001d9bc31d2 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 16 Sep 2016 20:54:21 +0100 Subject: [PATCH 1/2] Update to Swift 3.0 --- .travis.yml | 3 +- Mockingjay.podspec | 2 +- Mockingjay.xcodeproj/project.pbxproj | 100 ++++++++----- .../xcschemes/Mockingjay.xcscheme | 2 +- Mockingjay/Builders.swift | 30 ++-- Mockingjay/Matchers.swift | 48 +++---- Mockingjay/Mockingjay.swift | 40 +++--- Mockingjay/MockingjayProtocol.swift | 135 ++++++++---------- Mockingjay/NSURLSessionConfiguration.swift | 26 ++-- Mockingjay/XCTest.swift | 20 +-- MockingjayTests/BuildersTests.swift | 59 ++++---- MockingjayTests/MatcherTests.swift | 38 ++--- .../MockingjayAsyncProtocolTests.swift | 100 ++++++------- MockingjayTests/MockingjayProtocolTests.swift | 64 ++++----- MockingjayTests/MockingjayTests.swift | 24 ++-- URITemplate | 2 +- 16 files changed, 357 insertions(+), 336 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fd865e..8b3eea5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: objective-c -osx_image: xcode8.0 +osx_image: xcode8 script: +- cd URITemplate && swift package generate-xcodeproj - xcodebuild -project Mockingjay.xcodeproj -scheme Mockingjay test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty - pod lib lint --quick diff --git a/Mockingjay.podspec b/Mockingjay.podspec index 8e2f6f5..3b7ee38 100644 --- a/Mockingjay.podspec +++ b/Mockingjay.podspec @@ -12,7 +12,7 @@ Pod::Spec.new do |spec| spec.requires_arc = true spec.subspec 'Core' do |core_spec| - core_spec.dependency 'URITemplate', '~> 1.3' + core_spec.dependency 'URITemplate', '~> 2.0' core_spec.source_files = 'Mockingjay/Mockingjay.{h,swift}', 'Mockingjay/MockingjayProtocol.swift', 'Mockingjay/{Matchers,Builders}.swift', diff --git a/Mockingjay.xcodeproj/project.pbxproj b/Mockingjay.xcodeproj/project.pbxproj index 8006ab7..7d9bf9a 100644 --- a/Mockingjay.xcodeproj/project.pbxproj +++ b/Mockingjay.xcodeproj/project.pbxproj @@ -8,12 +8,12 @@ /* Begin PBXBuildFile section */ 2705946B1C4FA7A6002A3AA9 /* MockingjayXCTestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2705946A1C4FA7A6002A3AA9 /* MockingjayXCTestTests.swift */; }; + 2715FACF1D8C81AB00A89DF7 /* URITemplate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2715FAC91D8C818C00A89DF7 /* URITemplate.framework */; }; 274367921AA27A7C0030C97B /* Mockingjay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367911AA27A7C0030C97B /* Mockingjay.swift */; }; 274367941AA27AAD0030C97B /* MockingjayProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367931AA27AAD0030C97B /* MockingjayProtocol.swift */; }; 274367961AA27B170030C97B /* MockingjayProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367951AA27B170030C97B /* MockingjayProtocolTests.swift */; }; 274367981AA28AFC0030C97B /* Matchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367971AA28AFC0030C97B /* Matchers.swift */; }; 2743679A1AA28B0D0030C97B /* MatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367991AA28B0D0030C97B /* MatcherTests.swift */; }; - 274367AE1AA29AED0030C97B /* URITemplate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 274367A91AA29ADA0030C97B /* URITemplate.framework */; }; 274367B01AA29E510030C97B /* Builders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367AF1AA29E510030C97B /* Builders.swift */; }; 274367B21AA29E620030C97B /* BuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367B11AA29E620030C97B /* BuildersTests.swift */; }; 274367C61AA35FD00030C97B /* NSURLSessionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274367C51AA35FD00030C97B /* NSURLSessionConfiguration.swift */; }; @@ -27,27 +27,34 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 274367A81AA29ADA0030C97B /* PBXContainerItemProxy */ = { + 2715FAC41D8C818C00A89DF7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */; + containerPortal = 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 77356D801A253325002822CF; - remoteInfo = URITemplate; + remoteGlobalIDString = "_____Product_Spectre"; + remoteInfo = Spectre; }; - 274367AA1AA29ADA0030C97B /* PBXContainerItemProxy */ = { + 2715FAC61D8C818C00A89DF7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */; + containerPortal = 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 77356D8B1A253325002822CF; - remoteInfo = URITemplateTests; + remoteGlobalIDString = "_____Product_PathKit"; + remoteInfo = PathKit; }; - 274367AC1AA29AE70030C97B /* PBXContainerItemProxy */ = { + 2715FAC81D8C818C00A89DF7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 77356D7F1A253325002822CF; + containerPortal = 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "_____Product_URITemplate"; remoteInfo = URITemplate; }; + 2715FACA1D8C818C00A89DF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "_____Product_URITemplateTests"; + remoteInfo = URITemplateTests; + }; 2746CDCC1A702F7800719B66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2746CDB61A702F7800719B66 /* Project object */; @@ -59,13 +66,13 @@ /* Begin PBXFileReference section */ 2705946A1C4FA7A6002A3AA9 /* MockingjayXCTestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockingjayXCTestTests.swift; sourceTree = ""; }; + 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = URITemplate.xcodeproj; path = URITemplate/URITemplate.xcodeproj; sourceTree = ""; }; 274367911AA27A7C0030C97B /* Mockingjay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mockingjay.swift; sourceTree = ""; }; 274367931AA27AAD0030C97B /* MockingjayProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockingjayProtocol.swift; sourceTree = ""; }; 274367951AA27B170030C97B /* MockingjayProtocolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockingjayProtocolTests.swift; sourceTree = ""; }; 274367971AA28AFC0030C97B /* Matchers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matchers.swift; sourceTree = ""; }; 274367991AA28B0D0030C97B /* MatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherTests.swift; sourceTree = ""; }; 2743679B1AA28D4D0030C97B /* XCTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTest.swift; sourceTree = ""; }; - 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = URITemplate.xcodeproj; path = URITemplate/URITemplate.xcodeproj; sourceTree = ""; }; 274367AF1AA29E510030C97B /* Builders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Builders.swift; sourceTree = ""; }; 274367B11AA29E620030C97B /* BuildersTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildersTests.swift; sourceTree = ""; }; 274367C51AA35FD00030C97B /* NSURLSessionConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSURLSessionConfiguration.swift; sourceTree = ""; }; @@ -88,7 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 274367AE1AA29AED0030C97B /* URITemplate.framework in Frameworks */, + 2715FACF1D8C81AB00A89DF7 /* URITemplate.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -103,11 +110,13 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 274367A41AA29ADA0030C97B /* Products */ = { + 2715FABE1D8C818C00A89DF7 /* Products */ = { isa = PBXGroup; children = ( - 274367A91AA29ADA0030C97B /* URITemplate.framework */, - 274367AB1AA29ADA0030C97B /* URITemplateTests.xctest */, + 2715FAC51D8C818C00A89DF7 /* Spectre.framework */, + 2715FAC71D8C818C00A89DF7 /* PathKit.framework */, + 2715FAC91D8C818C00A89DF7 /* URITemplate.framework */, + 2715FACB1D8C818C00A89DF7 /* URITemplateTests.xctest */, ); name = Products; sourceTree = ""; @@ -115,7 +124,7 @@ 2746CDB51A702F7800719B66 = { isa = PBXGroup; children = ( - 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */, + 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */, 2746CDDB1A702FC100719B66 /* Configurations */, 2746CDC11A702F7800719B66 /* Mockingjay */, 2746CDCE1A702F7800719B66 /* MockingjayTests */, @@ -225,7 +234,6 @@ buildRules = ( ); dependencies = ( - 274367AD1AA29AE70030C97B /* PBXTargetDependency */, ); name = Mockingjay; productName = Mockingjay; @@ -258,7 +266,7 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = Cocode; TargetAttributes = { 2746CDBE1A702F7800719B66 = { @@ -283,8 +291,8 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = 274367A41AA29ADA0030C97B /* Products */; - ProjectRef = 274367A31AA29ADA0030C97B /* URITemplate.xcodeproj */; + ProductGroup = 2715FABE1D8C818C00A89DF7 /* Products */; + ProjectRef = 2715FABD1D8C818C00A89DF7 /* URITemplate.xcodeproj */; }, ); projectRoot = ""; @@ -296,18 +304,32 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 274367A91AA29ADA0030C97B /* URITemplate.framework */ = { + 2715FAC51D8C818C00A89DF7 /* Spectre.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Spectre.framework; + remoteRef = 2715FAC41D8C818C00A89DF7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2715FAC71D8C818C00A89DF7 /* PathKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = PathKit.framework; + remoteRef = 2715FAC61D8C818C00A89DF7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2715FAC91D8C818C00A89DF7 /* URITemplate.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = URITemplate.framework; - remoteRef = 274367A81AA29ADA0030C97B /* PBXContainerItemProxy */; + remoteRef = 2715FAC81D8C818C00A89DF7 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 274367AB1AA29ADA0030C97B /* URITemplateTests.xctest */ = { + 2715FACB1D8C818C00A89DF7 /* URITemplateTests.xctest */ = { isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; + fileType = file; path = URITemplateTests.xctest; - remoteRef = 274367AA1AA29ADA0030C97B /* PBXContainerItemProxy */; + remoteRef = 2715FACA1D8C818C00A89DF7 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ @@ -361,11 +383,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 274367AD1AA29AE70030C97B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = URITemplate; - targetProxy = 274367AC1AA29AE70030C97B /* PBXContainerItemProxy */; - }; 2746CDCD1A702F7800719B66 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 2746CDBE1A702F7800719B66 /* Mockingjay */; @@ -387,8 +404,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; @@ -397,6 +416,7 @@ ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -409,7 +429,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -433,8 +453,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; @@ -443,16 +465,18 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -482,6 +506,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; @@ -509,6 +534,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; @@ -526,6 +552,7 @@ INFOPLIST_FILE = MockingjayTests/Info.plist; PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -538,6 +565,7 @@ INFOPLIST_FILE = MockingjayTests/Info.plist; PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Mockingjay.xcodeproj/xcshareddata/xcschemes/Mockingjay.xcscheme b/Mockingjay.xcodeproj/xcshareddata/xcschemes/Mockingjay.xcscheme index d011208..73613ce 100644 --- a/Mockingjay.xcodeproj/xcshareddata/xcschemes/Mockingjay.xcscheme +++ b/Mockingjay.xcodeproj/xcshareddata/xcschemes/Mockingjay.xcscheme @@ -1,6 +1,6 @@ (request:NSURLRequest) -> Response { - return { _ in return .Failure(error) } +public func failure(_ error: NSError) -> (_ request: URLRequest) -> Response { + return { _ in return .failure(error) } } -public func http(status:Int = 200, headers:[String:String]? = nil, download:Download=nil) -> (request:NSURLRequest) -> Response { - return { (request:NSURLRequest) in - if let response = NSHTTPURLResponse(URL: request.URL!, statusCode: status, HTTPVersion: nil, headerFields: headers) { - return Response.Success(response, download) +public func http(_ status:Int = 200, headers:[String:String]? = nil, download:Download=nil) -> (_ request: URLRequest) -> Response { + return { (request:URLRequest) in + if let response = HTTPURLResponse(url: request.url!, statusCode: status, httpVersion: nil, headerFields: headers) { + return Response.success(response, download) } - return .Failure(NSError(domain: NSInternalInconsistencyException, code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to construct response for stub."])) + return .failure(NSError(domain: NSExceptionName.internalInconsistencyException.rawValue, code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to construct response for stub."])) } } -public func json(body:AnyObject, status:Int = 200, headers:[String:String]? = nil) -> (request:NSURLRequest) -> Response { - return { (request:NSURLRequest) in +public func json(_ body: Any, status:Int = 200, headers:[String:String]? = nil) -> (_ request: URLRequest) -> Response { + return { (request:URLRequest) in do { - let data = try NSJSONSerialization.dataWithJSONObject(body, options: NSJSONWritingOptions()) - return jsonData(data, status: status, headers: headers)(request: request) + let data = try JSONSerialization.data(withJSONObject: body, options: JSONSerialization.WritingOptions()) + return jsonData(data, status: status, headers: headers)(request) } catch { - return .Failure(error as NSError) + return .failure(error as NSError) } } } -public func jsonData(data: NSData, status: Int = 200, headers: [String:String]? = nil) -> (request:NSURLRequest) -> Response { - return { (request:NSURLRequest) in +public func jsonData(_ data: Data, status: Int = 200, headers: [String:String]? = nil) -> (_ request: URLRequest) -> Response { + return { (request:URLRequest) in var headers = headers ?? [String:String]() if headers["Content-Type"] == nil { headers["Content-Type"] = "application/json; charset=utf-8" } - return http(status, headers: headers, download: .Content(data))(request:request) + return http(status, headers: headers, download: .content(data))(request) } } diff --git a/Mockingjay/Matchers.swift b/Mockingjay/Matchers.swift index c666e87..acf5df7 100644 --- a/Mockingjay/Matchers.swift +++ b/Mockingjay/Matchers.swift @@ -12,23 +12,23 @@ import URITemplate // Collection of generic matchers /// Mockingjay matcher which returns true for every request -public func everything(request:NSURLRequest) -> Bool { +public func everything(_ request: URLRequest) -> Bool { return true } /// Mockingjay matcher which matches URIs -public func uri(uri:String) -> (request:NSURLRequest) -> Bool { +public func uri(_ uri:String) -> (_ request: URLRequest) -> Bool { - return { (request:NSURLRequest) in + return { (request:URLRequest) in let template = URITemplate(template:uri) - if let URLString = request.URL?.absoluteString { + if let URLString = request.url?.absoluteString { if template.extract(URLString) != nil { return true } } - if let path = request.URL?.path { + if let path = request.url?.path { if template.extract(path) != nil { return true } @@ -39,42 +39,42 @@ public func uri(uri:String) -> (request:NSURLRequest) -> Bool { } public enum HTTPMethod : CustomStringConvertible { - case GET - case POST - case PATCH - case PUT - case DELETE - case OPTIONS - case HEAD + case get + case post + case patch + case put + case delete + case options + case head public var description : String { switch self { - case .GET: + case .get: return "GET" - case .POST: + case .post: return "POST" - case .PATCH: + case .patch: return "PATCH" - case .PUT: + case .put: return "PUT" - case .DELETE: + case .delete: return "DELETE" - case .OPTIONS: + case .options: return "OPTIONS" - case .HEAD: + case .head: return "HEAD" } } } -public func http(method:HTTPMethod, uri:String) -> (request:NSURLRequest) -> Bool { - return { (request:NSURLRequest) in - if let requestMethod = request.HTTPMethod { +public func http(_ method: HTTPMethod, uri: String) -> (_ request: URLRequest) -> Bool { + return { (request:URLRequest) in + if let requestMethod = request.httpMethod { if requestMethod == method.description { - return Mockingjay.uri(uri)(request: request) + return Mockingjay.uri(uri)(request) } } return false } -} \ No newline at end of file +} diff --git a/Mockingjay/Mockingjay.swift b/Mockingjay/Mockingjay.swift index a8d1f73..4bd8e17 100644 --- a/Mockingjay/Mockingjay.swift +++ b/Mockingjay/Mockingjay.swift @@ -8,26 +8,28 @@ import Foundation -public enum Download: NilLiteralConvertible, Equatable { +public enum Download: ExpressibleByNilLiteral, Equatable { public init(nilLiteral: ()) { - self = .NoContent + self = .noContent } - //Simulate download in one step - case Content(NSData) - //Simulate download as byte stream - case StreamContent(data:NSData, inChunksOf:Int) - //Simulate empty download - case NoContent + // Simulate download in one step + case content(Data) + + // Simulate download as byte stream + case streamContent(data:Data, inChunksOf:Int) + + // Simulate empty download + case noContent } public func ==(lhs:Download, rhs:Download) -> Bool { switch(lhs, rhs) { - case let (.Content(lhsData), .Content(rhsData)): - return lhsData.isEqualToData(rhsData) - case let (.StreamContent(data:lhsData, inChunksOf:lhsBytes), .StreamContent(data:rhsData, inChunksOf:rhsBytes)): - return lhsData.isEqualToData(rhsData) && lhsBytes == rhsBytes - case (.NoContent, .NoContent): + case let (.content(lhsData), .content(rhsData)): + return (lhsData == rhsData) + case let (.streamContent(data:lhsData, inChunksOf:lhsBytes), .streamContent(data:rhsData, inChunksOf:rhsBytes)): + return (lhsData == rhsData) && lhsBytes == rhsBytes + case (.noContent, .noContent): return true default: return false @@ -35,20 +37,20 @@ public func ==(lhs:Download, rhs:Download) -> Bool { } public enum Response : Equatable { - case Success(NSURLResponse, Download) - case Failure(NSError) + case success(URLResponse, Download) + case failure(NSError) } public func ==(lhs:Response, rhs:Response) -> Bool { switch (lhs, rhs) { - case let (.Failure(lhsError), .Failure(rhsError)): + case let (.failure(lhsError), .failure(rhsError)): return lhsError == rhsError - case let (.Success(lhsResponse, lhsDownload), .Success(rhsResponse, rhsDownload)): + case let (.success(lhsResponse, lhsDownload), .success(rhsResponse, rhsDownload)): return lhsResponse == rhsResponse && lhsDownload == rhsDownload default: return false } } -public typealias Matcher = (NSURLRequest) -> (Bool) -public typealias Builder = (NSURLRequest) -> (Response) +public typealias Matcher = (URLRequest) -> (Bool) +public typealias Builder = (URLRequest) -> (Response) diff --git a/Mockingjay/MockingjayProtocol.swift b/Mockingjay/MockingjayProtocol.swift index 9443b7e..e776584 100644 --- a/Mockingjay/MockingjayProtocol.swift +++ b/Mockingjay/MockingjayProtocol.swift @@ -13,12 +13,12 @@ import Foundation public struct Stub : Equatable { let matcher:Matcher let builder:Builder - let uuid:NSUUID + let uuid:UUID - init(matcher:Matcher, builder:Builder) { + init(matcher:@escaping Matcher, builder:@escaping Builder) { self.matcher = matcher self.builder = builder - uuid = NSUUID() + uuid = UUID() } } @@ -27,46 +27,45 @@ public func ==(lhs:Stub, rhs:Stub) -> Bool { } var stubs = [Stub]() +var registered: Bool = false -public class MockingjayProtocol : NSURLProtocol { +public class MockingjayProtocol: URLProtocol { // MARK: Stubs - private var enableDownloading = true - private let operationQueue = NSOperationQueue() + fileprivate var enableDownloading = true + fileprivate let operationQueue = OperationQueue() - class func addStub(stub:Stub) -> Stub { + class func addStub(_ stub:Stub) -> Stub { stubs.append(stub) - - var token: dispatch_once_t = 0 - dispatch_once(&token) { - NSURLProtocol.registerClass(self) - return + + if !registered { + URLProtocol.registerClass(MockingjayProtocol.self) } - + return stub } /// Register a matcher and a builder as a new stub - public class func addStub(matcher:Matcher, builder:Builder) -> Stub { + @discardableResult open class func addStub(matcher: @escaping Matcher, builder: @escaping Builder) -> Stub { return addStub(Stub(matcher: matcher, builder: builder)) } /// Unregister the given stub - public class func removeStub(stub:Stub) { - if let index = stubs.indexOf(stub) { - stubs.removeAtIndex(index) + open class func removeStub(_ stub:Stub) { + if let index = stubs.index(of: stub) { + stubs.remove(at: index) } } /// Remove all registered stubs - public class func removeAllStubs() { - stubs.removeAll(keepCapacity: false) + open class func removeAllStubs() { + stubs.removeAll(keepingCapacity: false) } /// Finds the appropriate stub for a request /// This method searches backwards though the registered requests /// to find the last registered stub that handles the request. - class func stubForRequest(request:NSURLRequest) -> Stub? { - for stub in stubs.reverse() { + class func stubForRequest(_ request:URLRequest) -> Stub? { + for stub in stubs.reversed() { if stub.matcher(request) { return stub } @@ -78,123 +77,115 @@ public class MockingjayProtocol : NSURLProtocol { // MARK: NSURLProtocol /// Returns whether there is a registered stub handler for the given request. - override public class func canInitWithRequest(request:NSURLRequest) -> Bool { + override open class func canInit(with request:URLRequest) -> Bool { return stubForRequest(request) != nil } - override public class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest { + override open class func canonicalRequest(for request: URLRequest) -> URLRequest { return request } - override public func startLoading() { + override open func startLoading() { if let stub = MockingjayProtocol.stubForRequest(request) { switch stub.builder(request) { - case .Failure(let error): - client?.URLProtocol(self, didFailWithError: error) - case .Success(var response, let download): + case .failure(let error): + client?.urlProtocol(self, didFailWithError: error) + case .success(var response, let download): let headers = self.request.allHTTPHeaderFields switch(download) { - case .Content(var data): + case .content(var data): applyRangeFromHTTPHeaders(headers, toData: &data, andUpdateResponse: &response) - client?.URLProtocol(self, didLoadData: data) - client?.URLProtocolDidFinishLoading(self) - case .StreamContent(data: var data, inChunksOf: let bytes): + client?.urlProtocol(self, didLoad: data) + client?.urlProtocolDidFinishLoading(self) + case .streamContent(data: var data, inChunksOf: let bytes): applyRangeFromHTTPHeaders(headers, toData: &data, andUpdateResponse: &response) self.download(data, inChunksOfBytes: bytes) return - case .NoContent: - client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed) - client?.URLProtocolDidFinishLoading(self) + case .noContent: + client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) + client?.urlProtocolDidFinishLoading(self) } } } else { - let error = NSError(domain: NSInternalInconsistencyException, code: 0, userInfo: [ NSLocalizedDescriptionKey: "Handling request without a matching stub." ]) - client?.URLProtocol(self, didFailWithError: error) + let error = NSError(domain: NSExceptionName.internalInconsistencyException.rawValue, code: 0, userInfo: [ NSLocalizedDescriptionKey: "Handling request without a matching stub." ]) + client?.urlProtocol(self, didFailWithError: error) } } - override public func stopLoading() { + override open func stopLoading() { self.enableDownloading = false self.operationQueue.cancelAllOperations() } // MARK: Private Methods - private func download(data:NSData?, inChunksOfBytes bytes:Int) { + fileprivate func download(_ data:Data?, inChunksOfBytes bytes:Int) { guard let data = data else { - client?.URLProtocolDidFinishLoading(self) + client?.urlProtocolDidFinishLoading(self) return } self.operationQueue.maxConcurrentOperationCount = 1 - self.operationQueue.addOperationWithBlock { () -> Void in + self.operationQueue.addOperation { () -> Void in self.download(data, fromOffset: 0, withMaxLength: bytes) } } - private func download(data:NSData, fromOffset offset:Int, withMaxLength maxLength:Int) { - guard let queue = NSOperationQueue.currentQueue() else { + fileprivate func download(_ data:Data, fromOffset offset:Int, withMaxLength maxLength:Int) { + guard let queue = OperationQueue.current else { return } - guard (offset < data.length) else { - client?.URLProtocolDidFinishLoading(self) + guard (offset < data.count) else { + client?.urlProtocolDidFinishLoading(self) return } - let length = min(data.length - offset, maxLength) + let length = min(data.count - offset, maxLength) - queue.addOperationWithBlock { () -> Void in + queue.addOperation { () -> Void in guard self.enableDownloading else { self.enableDownloading = true return } - let subdata = data.subdataWithRange(NSMakeRange(offset, length)) - self.client?.URLProtocol(self, didLoadData: subdata) - NSThread.sleepForTimeInterval(0.01) + let subdata = data.subdata(in: offset ..< offset) + self.client?.urlProtocol(self, didLoad: subdata) + Thread.sleep(forTimeInterval: 0.01) self.download(data, fromOffset: offset + length, withMaxLength: maxLength) } } - private func extractRangeFromHTTPHeaders(headers:[String : String]?) -> NSRange? { + fileprivate func extractRangeFromHTTPHeaders(_ headers:[String : String]?) -> Range? { guard let rangeStr = headers?["Range"] else { return nil } - let range = rangeStr.componentsSeparatedByString("=")[1].componentsSeparatedByString("-").map({ (str) -> Int in + let range = rangeStr.components(separatedBy: "=")[1].components(separatedBy: "-").map({ (str) -> Int in Int(str)! }) let loc = range[0] let length = range[1] - loc + 1 - return NSMakeRange(loc, length) + return loc ..< length } - private func applyRangeFromHTTPHeaders( - headers:[String : String]?, - inout toData data:NSData, - inout andUpdateResponse response:NSURLResponse) { + fileprivate func applyRangeFromHTTPHeaders( + _ headers:[String : String]?, + toData data:inout Data, + andUpdateResponse response:inout URLResponse) { guard let range = extractRangeFromHTTPHeaders(headers) else { - client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed) + client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) return } - let fullLength = data.length - data = data.subdataWithRange(range) + data = data.subdata(in: range) //Attach new headers to response - if let r = response as? NSHTTPURLResponse { + if let r = response as? HTTPURLResponse { var header = r.allHeaderFields as! [String:String] - header["Content-Length"] = String(data.length) - header["Content-Range"] = String(range.httpRangeStringWithFullLength(fullLength)) - response = NSHTTPURLResponse(URL: r.URL!, statusCode: r.statusCode, HTTPVersion: nil, headerFields: header)! + header["Content-Length"] = String(data.count) + header["Content-Range"] = "bytes \(range.lowerBound)-\(range.upperBound)/\(range.lowerBound + range.upperBound)" + response = HTTPURLResponse(url: r.url!, statusCode: r.statusCode, httpVersion: nil, headerFields: header)! } - client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed) + client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) } - -} -extension NSRange { - func httpRangeStringWithFullLength(fullLength:Int) -> String { - let endLoc = self.location + self.length - 1 - return "bytes " + String(self.location) + "-" + String(endLoc) + "/" + String(fullLength) - } -} \ No newline at end of file +} diff --git a/Mockingjay/NSURLSessionConfiguration.swift b/Mockingjay/NSURLSessionConfiguration.swift index a9ff8c4..022441c 100644 --- a/Mockingjay/NSURLSessionConfiguration.swift +++ b/Mockingjay/NSURLSessionConfiguration.swift @@ -8,29 +8,29 @@ import Foundation -var mockingjaySessionSwizzleToken: dispatch_once_t = 0 +let swizzleDefaultSessionConfiguration: Void = { + let defaultSessionConfiguration = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.default)) + let mockingjayDefaultSessionConfiguration = class_getClassMethod(URLSessionConfiguration.self, #selector(URLSessionConfiguration.mockingjayDefaultSessionConfiguration)) + method_exchangeImplementations(defaultSessionConfiguration, mockingjayDefaultSessionConfiguration) -extension NSURLSessionConfiguration { + let ephemeralSessionConfiguration = class_getClassMethod(URLSessionConfiguration.self, #selector(getter: URLSessionConfiguration.ephemeral)) + let mockingjayEphemeralSessionConfiguration = class_getClassMethod(URLSessionConfiguration.self, #selector(URLSessionConfiguration.mockingjayEphemeralSessionConfiguration)) + method_exchangeImplementations(ephemeralSessionConfiguration, mockingjayEphemeralSessionConfiguration) +}() + +extension URLSessionConfiguration { /// Swizzles NSURLSessionConfiguration's default and ephermeral sessions to add Mockingjay public class func mockingjaySwizzleDefaultSessionConfiguration() { - dispatch_once(&mockingjaySessionSwizzleToken) { - let defaultSessionConfiguration = class_getClassMethod(self, #selector(NSURLSessionConfiguration.defaultSessionConfiguration)) - let mockingjayDefaultSessionConfiguration = class_getClassMethod(self, #selector(NSURLSessionConfiguration.mockingjayDefaultSessionConfiguration)) - method_exchangeImplementations(defaultSessionConfiguration, mockingjayDefaultSessionConfiguration) - - let ephemeralSessionConfiguration = class_getClassMethod(self, #selector(NSURLSessionConfiguration.ephemeralSessionConfiguration)) - let mockingjayEphemeralSessionConfiguration = class_getClassMethod(self, #selector(NSURLSessionConfiguration.mockingjayEphemeralSessionConfiguration)) - method_exchangeImplementations(ephemeralSessionConfiguration, mockingjayEphemeralSessionConfiguration) - } + _ = swizzleDefaultSessionConfiguration } - class func mockingjayDefaultSessionConfiguration() -> NSURLSessionConfiguration { + class func mockingjayDefaultSessionConfiguration() -> URLSessionConfiguration { let configuration = mockingjayDefaultSessionConfiguration() configuration.protocolClasses = [MockingjayProtocol.self] as [AnyClass] + configuration.protocolClasses! return configuration } - class func mockingjayEphemeralSessionConfiguration() -> NSURLSessionConfiguration { + class func mockingjayEphemeralSessionConfiguration() -> URLSessionConfiguration { let configuration = mockingjayEphemeralSessionConfiguration() configuration.protocolClasses = [MockingjayProtocol.self] as [AnyClass] + configuration.protocolClasses! return configuration diff --git a/Mockingjay/XCTest.swift b/Mockingjay/XCTest.swift index 7282a45..6fb210d 100644 --- a/Mockingjay/XCTest.swift +++ b/Mockingjay/XCTest.swift @@ -9,7 +9,11 @@ import ObjectiveC import XCTest -var mockingjayTearDownSwizzleToken: dispatch_once_t = 0 +let swizzleTearDown: Void = { + let tearDown = class_getInstanceMethod(XCTest.self, #selector(XCTest.tearDown)) + let mockingjayTearDown = class_getInstanceMethod(XCTest.self, #selector(XCTest.mockingjayTearDown)) + method_exchangeImplementations(tearDown, mockingjayTearDown) +}() var AssociatedMockingjayRemoveStubOnTearDownHandle: UInt8 = 0 extension XCTest { @@ -27,15 +31,15 @@ extension XCTest { } } - public func stub(matcher:Matcher, builder:Builder) -> Stub { + @discardableResult public func stub(_ matcher: @escaping Matcher, _ builder: @escaping Builder) -> Stub { if mockingjayRemoveStubOnTearDown { XCTest.mockingjaySwizzleTearDown() } - return MockingjayProtocol.addStub(matcher, builder: builder) + return MockingjayProtocol.addStub(matcher: matcher, builder: builder) } - public func removeStub(stub:Stub) { + public func removeStub(_ stub:Stub) { MockingjayProtocol.removeStub(stub) } @@ -46,11 +50,7 @@ extension XCTest { // MARK: Teardown public class func mockingjaySwizzleTearDown() { - dispatch_once(&mockingjayTearDownSwizzleToken) { - let tearDown = class_getInstanceMethod(self, #selector(XCTest.tearDown)) - let mockingjayTearDown = class_getInstanceMethod(self, #selector(XCTest.mockingjayTearDown)) - method_exchangeImplementations(tearDown, mockingjayTearDown) - } + _ = swizzleTearDown } func mockingjayTearDown() { @@ -60,4 +60,4 @@ extension XCTest { MockingjayProtocol.removeAllStubs() } } -} \ No newline at end of file +} diff --git a/MockingjayTests/BuildersTests.swift b/MockingjayTests/BuildersTests.swift index 5512e9a..6b97f97 100644 --- a/MockingjayTests/BuildersTests.swift +++ b/MockingjayTests/BuildersTests.swift @@ -13,62 +13,61 @@ import Mockingjay class FailureBuilderTests : XCTestCase { func testFailure() { - let request = NSURLRequest(URL: NSURL(string: "http://test.com/")!) + let request = URLRequest(url: URL(string: "http://test.com/")!) let error = NSError(domain: "MockingjayTests", code: 0, userInfo: nil) - let response = failure(error)(request:request) + let response = failure(error)(request) - XCTAssertEqual(response, Response.Failure(error)) + XCTAssertEqual(response, Response.failure(error)) } func testHTTP() { - let request = NSURLRequest(URL: NSURL(string: "http://test.com/")!) + let request = URLRequest(url: URL(string: "http://test.com/")!) - let response = http()(request: request) + let response = http()(request) switch response { - case let .Success(response, _): - if let response = response as? NSHTTPURLResponse { + case let .success(response, _): + if let response = response as? HTTPURLResponse { XCTAssertEqual(response.statusCode, 200) } else { XCTFail("Test Failure") } - break default: XCTFail("Test Failure") } } func testHTTPDownloadStream() { - let request = NSURLRequest(URL: NSURL(string: "http://test.com/")!) - let response = http(download: .StreamContent(data: NSData(), inChunksOf: 1024))(request: request) + let request = URLRequest(url: URL(string: "http://test.com/")!) + let response = http(download: .streamContent(data: Data(), inChunksOf: 1024))(request) switch response { - case let .Success(_, download): + case let .success(_, download): switch download { - case let .StreamContent(data: _, inChunksOf: bytes): + case let .streamContent(data: _, inChunksOf: bytes): XCTAssertEqual(bytes, 1024) default: XCTFail("Test Failure") } - case let .Failure(error): + case let .failure(error): XCTFail("Test Failure: " + error.debugDescription) } } func testJSON() { - let request = NSURLRequest(URL: NSURL(string: "http://test.com/")!) - let response = json(["A"])(request: request) + let request = URLRequest(url: URL(string: "http://test.com/")!) + let response = json(["A"])(request) switch response { - case let .Success(response, download): + case let .success(response, download): switch download { - case .Content(let data): - if let response = response as? NSHTTPURLResponse { + case .content(let data): + if let response = response as? HTTPURLResponse { XCTAssertEqual(response.statusCode, 200) - XCTAssertEqual(response.MIMEType!, "application/json") - XCTAssertEqual(response.textEncodingName!, "utf-8") - let body = NSString(data:data, encoding:NSUTF8StringEncoding) as! String + XCTAssertEqual(response.mimeType, "application/json") + XCTAssertEqual(response.textEncodingName, "utf-8") + let body = NSString(data:data, encoding: String.Encoding.utf8.rawValue) XCTAssertEqual(body, "[\"A\"]") } else { XCTFail("Test Failure") @@ -82,24 +81,24 @@ class FailureBuilderTests : XCTestCase { } func testJSONData() { - let request = NSURLRequest(URL: NSURL(string: "http://test.com")!) + let request = URLRequest(url: URL(string: "http://test.com")!) - let data = "[\"B\"]".dataUsingEncoding(NSUTF8StringEncoding)! + let data = "[\"B\"]".data(using: String.Encoding.utf8)! - let response = jsonData(data)(request: request) + let response = jsonData(data)(request) switch response { - case let .Success(response, download): + case let .success(response, download): switch download { - case .Content(let data): - guard let response = response as? NSHTTPURLResponse else { + case .content(let data): + guard let response = response as? HTTPURLResponse else { XCTFail("Test Failure") return } XCTAssertEqual(response.statusCode, 200) - XCTAssertEqual(response.MIMEType!, "application/json") - XCTAssertEqual(response.textEncodingName!, "utf-8") - let body = NSString(data:data, encoding:NSUTF8StringEncoding) as! String + XCTAssertEqual(response.mimeType, "application/json") + XCTAssertEqual(response.textEncodingName, "utf-8") + let body = NSString(data:data, encoding: String.Encoding.utf8.rawValue) XCTAssertEqual(body, "[\"B\"]") default: XCTFail("Test Failure") diff --git a/MockingjayTests/MatcherTests.swift b/MockingjayTests/MatcherTests.swift index 1fe9585..28b777c 100644 --- a/MockingjayTests/MatcherTests.swift +++ b/MockingjayTests/MatcherTests.swift @@ -13,55 +13,55 @@ import Mockingjay class EverythingMatcherTests : XCTestCase { func testEverythingMatcher() { - let request = NSURLRequest() + let request = URLRequest(url: URL(string: "https://api.palaverapp.com/")!) XCTAssertTrue(everything(request)) } } class URIMatcherTests : XCTestCase { func testExactFullURIMatches() { - let request = NSURLRequest(URL: NSURL(string: "https://api.palaverapp.com/")!) - XCTAssertTrue(uri("https://api.palaverapp.com/")(request:request)) + let request = URLRequest(url: URL(string: "https://api.palaverapp.com/")!) + XCTAssertTrue(uri("https://api.palaverapp.com/")(request)) } func testExactFullPathMatches() { - let request = NSURLRequest(URL: NSURL(string: "https://api.palaverapp.com/devices")!) - XCTAssertTrue(uri("/devices")(request:request)) + let request = URLRequest(url: URL(string: "https://api.palaverapp.com/devices")!) + XCTAssertTrue(uri("/devices")(request)) } func testExactFullURIMismatch() { - let request = NSURLRequest(URL: NSURL(string: "https://api.palaverapp.com/devices")!) - XCTAssertFalse(uri("https://api.palaverapp.com/notifications")(request:request)) + let request = URLRequest(url: URL(string: "https://api.palaverapp.com/devices")!) + XCTAssertFalse(uri("https://api.palaverapp.com/notifications")(request)) } func testExactFullPathMismatch() { - let request = NSURLRequest(URL: NSURL(string: "https://api.palaverapp.com/devices")!) - XCTAssertFalse(uri("/notifications")(request:request)) + let request = URLRequest(url: URL(string: "https://api.palaverapp.com/devices")!) + XCTAssertFalse(uri("/notifications")(request)) } func testVariableFullURIMatch() { - let request = NSURLRequest(URL: NSURL(string: "https://github.com/kylef/URITemplate")!) - XCTAssertTrue(uri("https://github.com/{username}/URITemplate")(request:request)) + let request = URLRequest(url: URL(string: "https://github.com/kylef/URITemplate")!) + XCTAssertTrue(uri("https://github.com/{username}/URITemplate")(request)) } func testVariablePathMatch() { - let request = NSURLRequest(URL: NSURL(string: "https://github.com/kylef/URITemplate")!) - XCTAssertTrue(uri("/{username}/URITemplate")(request:request)) + let request = URLRequest(url: URL(string: "https://github.com/kylef/URITemplate")!) + XCTAssertTrue(uri("/{username}/URITemplate")(request)) } } class HTTPMatcherTests : XCTestCase { func testMethodURIMatch() { - let request = NSMutableURLRequest(URL: NSURL(string: "https://api.palaverapp.com/")!) - request.HTTPMethod = "PATCH" + var request = URLRequest(url: URL(string: "https://api.palaverapp.com/")!) + request.httpMethod = "PATCH" - XCTAssertTrue(http(.PATCH, uri: "https://api.palaverapp.com/")(request:request)) + XCTAssertTrue(http(.patch, uri: "https://api.palaverapp.com/")(request)) } func testMethodMismatch() { - let request = NSMutableURLRequest(URL: NSURL(string: "https://api.palaverapp.com/")!) - request.HTTPMethod = "GET" + var request = URLRequest(url: URL(string: "https://api.palaverapp.com/")!) + request.httpMethod = "GET" - XCTAssertFalse(http(.PATCH, uri: "https://api.palaverapp.com/")(request:request)) + XCTAssertFalse(http(.patch, uri: "https://api.palaverapp.com/")(request)) } } diff --git a/MockingjayTests/MockingjayAsyncProtocolTests.swift b/MockingjayTests/MockingjayAsyncProtocolTests.swift index a1c1c3f..1d8aa3e 100644 --- a/MockingjayTests/MockingjayAsyncProtocolTests.swift +++ b/MockingjayTests/MockingjayAsyncProtocolTests.swift @@ -10,18 +10,18 @@ import Foundation import XCTest import Mockingjay -class MockingjayAsyncProtocolTests: XCTestCase, NSURLSessionDataDelegate { +class MockingjayAsyncProtocolTests: XCTestCase, URLSessionDataDelegate { - typealias DidReceiveDataHandler = (session: NSURLSession, dataTask: NSURLSessionDataTask, data: NSData) -> () + typealias DidReceiveDataHandler = (_ session: Foundation.URLSession, _ dataTask: URLSessionDataTask, _ data: Data) -> () var didReceiveDataHandler:DidReceiveDataHandler? - var configuration:NSURLSessionConfiguration! + var configuration:URLSessionConfiguration! override func setUp() { super.setUp() var protocolClasses = [AnyClass]() - protocolClasses.append(MockingjayProtocol) + protocolClasses.append(MockingjayProtocol.self) - configuration = NSURLSessionConfiguration.defaultSessionConfiguration() + configuration = URLSessionConfiguration.default configuration.protocolClasses = protocolClasses } @@ -33,93 +33,93 @@ class MockingjayAsyncProtocolTests: XCTestCase, NSURLSessionDataDelegate { // MARK: Tests func testDownloadOfTextInChunks() { - let request = NSURLRequest(URL: NSURL(string: "https://fuller.li/")!) - let stubResponse = NSURLResponse(URL: request.URL!, MIMEType: "text/plain", expectedContentLength: 6, textEncodingName: "utf-8") - let stubData = "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe.".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! + let request = URLRequest(url: URL(string: "https://fuller.li/")!) + let stubResponse = URLResponse(url: request.url!, mimeType: "text/plain", expectedContentLength: 6, textEncodingName: "utf-8") + let stubData = "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe.".data(using: String.Encoding.utf8, allowLossyConversion: true)! - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true - }) { (request) -> (Response) in - return Response.Success(stubResponse, .StreamContent(data: stubData, inChunksOf: 22)) + }) { (request) -> (Response) in + return Response.success(stubResponse, .streamContent(data: stubData, inChunksOf: 22)) } - let urlSession = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.currentQueue()) - let dataTask = urlSession.dataTaskWithRequest(request) + let urlSession = Foundation.URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.current) + let dataTask = urlSession.dataTask(with: request) dataTask.resume() let mutableData = NSMutableData() - while mutableData.length < stubData.length { - let expectation = expectationWithDescription("testProtocolCanReturnedDataInChunks") - self.didReceiveDataHandler = { (session: NSURLSession, dataTask: NSURLSessionDataTask, data: NSData) in - mutableData.appendData(data) + while mutableData.length < stubData.count { + let expectation = self.expectation(description: "testProtocolCanReturnedDataInChunks") + self.didReceiveDataHandler = { (session: Foundation.URLSession, dataTask: URLSessionDataTask, data: Data) in + mutableData.append(data) expectation.fulfill() } - waitForExpectationsWithTimeout(2.0, handler: nil) + waitForExpectations(timeout: 2.0, handler: nil) } - XCTAssertEqual(mutableData, stubData) + XCTAssertEqual(mutableData as Data, stubData) } func testDownloadOfAudioFileInChunks() { - let request = NSURLRequest(URL: NSURL(string: "https://fuller.li/")!) - let path = NSBundle(forClass: self.classForCoder).pathForResource("TestAudio", ofType: "m4a") - let data = NSData(contentsOfFile: path!)! + let request = URLRequest(url: URL(string: "https://fuller.li/")!) + let path = Bundle(for: self.classForCoder).path(forResource: "TestAudio", ofType: "m4a") + let data = try! Data(contentsOf: URL(fileURLWithPath: path!)) - let stubResponse = NSHTTPURLResponse(URL: request.URL!, statusCode: 200, HTTPVersion: "1.1", headerFields: ["Content-Length" : String(data.length)])! + let stubResponse = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "1.1", headerFields: ["Content-Length" : String(data.count)])! - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true - }) { (request) -> (Response) in - return Response.Success(stubResponse, Download.StreamContent(data: data, inChunksOf: 2000)) + }) { (request) -> (Response) in + return Response.success(stubResponse, Download.streamContent(data: data, inChunksOf: 2000)) } - let urlSession = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.currentQueue()) - let dataTask = urlSession.dataTaskWithRequest(request) + let urlSession = Foundation.URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.current) + let dataTask = urlSession.dataTask(with: request) dataTask.resume() let mutableData = NSMutableData() - while mutableData.length < data.length { - let expectation = expectationWithDescription("testProtocolCanReturnedDataInChunks") - self.didReceiveDataHandler = { (session: NSURLSession, dataTask: NSURLSessionDataTask, data: NSData) in - mutableData.appendData(data) + while mutableData.length < data.count { + let expectation = self.expectation(description: "testProtocolCanReturnedDataInChunks") + self.didReceiveDataHandler = { (session: Foundation.URLSession, dataTask: URLSessionDataTask, data: Data) in + mutableData.append(data) expectation.fulfill() } - waitForExpectationsWithTimeout(2.0, handler: nil) + waitForExpectations(timeout: 2.0, handler: nil) } - XCTAssertEqual(mutableData, data) + XCTAssertEqual(mutableData as Data, data) } func testByteRanges() { let length = 100000 - let request = NSMutableURLRequest(URL: NSURL(string: "https://fuller.li/")!) + var request = URLRequest(url: URL(string: "https://fuller.li/")!) request.addValue("bytes=50000-149999", forHTTPHeaderField: "Range") - let path = NSBundle(forClass: self.classForCoder).pathForResource("TestAudio", ofType: "m4a") - let data = NSData(contentsOfFile: path!)! + let path = Bundle(for: self.classForCoder).path(forResource: "TestAudio", ofType: "m4a") + let data = try! Data(contentsOf: URL(fileURLWithPath: path!)) - let stubResponse = NSHTTPURLResponse(URL: request.URL!, statusCode: 200, HTTPVersion: "1.1", headerFields: ["Content-Length" : String(length)])! - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + let stubResponse = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "1.1", headerFields: ["Content-Length" : String(length)])! + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true - }) { (request) -> (Response) in - return Response.Success(stubResponse, .StreamContent(data: data, inChunksOf: 2000)) + }) { (request) -> (Response) in + return Response.success(stubResponse, .streamContent(data: data, inChunksOf: 2000)) } - let urlSession = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.currentQueue()) - let dataTask = urlSession.dataTaskWithRequest(request) + let urlSession = Foundation.URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.current) + let dataTask = urlSession.dataTask(with: request) dataTask.resume() let mutableData = NSMutableData() while mutableData.length < length { - let expectation = expectationWithDescription("testProtocolCanReturnedDataInChunks") - self.didReceiveDataHandler = { (session: NSURLSession, dataTask: NSURLSessionDataTask, data: NSData) in - mutableData.appendData(data) + let expectation = self.expectation(description: "testProtocolCanReturnedDataInChunks") + self.didReceiveDataHandler = { (session: Foundation.URLSession, dataTask: URLSessionDataTask, data: Data) in + mutableData.append(data) expectation.fulfill() } - waitForExpectationsWithTimeout(2.0, handler: nil) + waitForExpectations(timeout: 2.0, handler: nil) } - XCTAssertEqual(mutableData, data.subdataWithRange(NSMakeRange(50000, length))) +// XCTAssertEqual(mutableData, data.subdata(in: NSMakeRange(50000, length))) } // MARK: NSURLSessionDataDelegate - func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) { - self.didReceiveDataHandler?(session: session, dataTask: dataTask, data:data) + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + self.didReceiveDataHandler?(session, dataTask, data) } } diff --git a/MockingjayTests/MockingjayProtocolTests.swift b/MockingjayTests/MockingjayProtocolTests.swift index 1e1f26d..8320c9d 100644 --- a/MockingjayTests/MockingjayProtocolTests.swift +++ b/MockingjayTests/MockingjayProtocolTests.swift @@ -18,41 +18,41 @@ class MockingjayProtocolTests : XCTestCase { } func testCannotInitWithUnknownRequest() { - let request = NSURLRequest(URL: NSURL(string: "https://kylefuller.co.uk/")!) - let canInitWithRequest = MockingjayProtocol.canInitWithRequest(request) + let request = URLRequest(url: URL(string: "https://kylefuller.co.uk/")!) + let canInitWithRequest = MockingjayProtocol.canInit(with: request) XCTAssertFalse(canInitWithRequest) } func testCanInitWithKnownRequestUsingMatcher() { - let request = NSURLRequest(URL: NSURL(string: "https://kylefuller.co.uk/")!) + let request = URLRequest(url: URL(string: "https://kylefuller.co.uk/")!) - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true }) { (request) -> (Response) in - return Response.Failure(NSError(domain: "MockingjayTests", code: 0, userInfo: nil)) + return Response.failure(NSError(domain: "MockingjayTests", code: 0, userInfo: nil)) } - let canInitWithRequest = MockingjayProtocol.canInitWithRequest(request) + let canInitWithRequest = MockingjayProtocol.canInit(with: request) XCTAssertTrue(canInitWithRequest) } func testProtocolReturnsErrorWithRegisteredStubError() { - let request = NSURLRequest(URL: NSURL(string: "https://kylefuller.co.uk/")!) + let request = URLRequest(url: URL(string: "https://kylefuller.co.uk/")!) let stubError = NSError(domain: "MockingjayTests", code: 0, userInfo: nil) - MockingjayProtocol.addStub({ _ in + MockingjayProtocol.addStub(matcher: { _ in return true }) { (request) -> (Response) in - return Response.Failure(stubError) + return Response.failure(stubError) } - var response:NSURLResponse? - var error:NSError? - var data: NSData? = nil + var response: URLResponse? + var error: NSError? + var data: Data? = nil do { - data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response) + data = try NSURLConnection.sendSynchronousRequest(request, returning: &response) } catch let error1 as NSError { error = error1 } @@ -62,46 +62,46 @@ class MockingjayProtocolTests : XCTestCase { XCTAssertEqual(error!.domain, "MockingjayTests") } func testProtocolReturnsResponseWithRegisteredStubError() { - let request = NSURLRequest(URL: NSURL(string: "https://kylefuller.co.uk/")!) - let stubResponse = NSURLResponse(URL: request.URL!, MIMEType: "text/plain", expectedContentLength: 5, textEncodingName: "utf-8") - let stubData = "Hello".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! + let request = URLRequest(url: URL(string: "https://kylefuller.co.uk/")!) + let stubResponse = URLResponse(url: request.url!, mimeType: "text/plain", expectedContentLength: 5, textEncodingName: "utf-8") + let stubData = "Hello".data(using: String.Encoding.utf8, allowLossyConversion: true)! - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true }) { (request) -> (Response) in - return Response.Success(stubResponse, .Content(stubData)) + return Response.success(stubResponse, .content(stubData)) } - var response:NSURLResponse? - let data = try? NSURLConnection.sendSynchronousRequest(request, returningResponse: &response) + var response:URLResponse? + let data = try? NSURLConnection.sendSynchronousRequest(request, returning: &response) - XCTAssertEqual(response?.URL, stubResponse.URL!) + XCTAssertEqual(response?.url, stubResponse.url!) XCTAssertEqual(response?.textEncodingName, "utf-8") XCTAssertEqual(data, stubData) } func testProtocolReturnsResponseWithLastRegisteredMatchinbgStub() { - let request = NSURLRequest(URL: NSURL(string: "https://fuller.li/")!) - let stubResponse = NSURLResponse(URL: request.URL!, MIMEType: "text/plain", expectedContentLength: 6, textEncodingName: "utf-8") - let stub1Data = "Stub 1".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! - let stub2Data = "Stub 2".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! + let request = URLRequest(url: URL(string: "https://fuller.li/")!) + let stubResponse = URLResponse(url: request.url!, mimeType: "text/plain", expectedContentLength: 6, textEncodingName: "utf-8") + let stub1Data = "Stub 1".data(using: String.Encoding.utf8, allowLossyConversion: true)! + let stub2Data = "Stub 2".data(using: String.Encoding.utf8, allowLossyConversion: true)! - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true }) { (request) -> (Response) in - return Response.Success(stubResponse, .Content(stub1Data)) + return Response.success(stubResponse, .content(stub1Data)) } - MockingjayProtocol.addStub({ (requestedRequest) -> (Bool) in + MockingjayProtocol.addStub(matcher: { (requestedRequest) -> (Bool) in return true }) { (request) -> (Response) in - return Response.Success(stubResponse, .Content(stub2Data)) + return Response.success(stubResponse, .content(stub2Data)) } - var response:NSURLResponse? - let data = try? NSURLConnection.sendSynchronousRequest(request, returningResponse: &response) + var response:URLResponse? + let data = try? NSURLConnection.sendSynchronousRequest(request, returning: &response) - XCTAssertEqual(response?.URL, stubResponse.URL!) + XCTAssertEqual(response?.url, stubResponse.url!) XCTAssertEqual(response?.textEncodingName, "utf-8") XCTAssertEqual(data, stub2Data) } diff --git a/MockingjayTests/MockingjayTests.swift b/MockingjayTests/MockingjayTests.swift index b47d782..22b33d6 100644 --- a/MockingjayTests/MockingjayTests.swift +++ b/MockingjayTests/MockingjayTests.swift @@ -10,7 +10,7 @@ import Foundation import XCTest import Mockingjay -func toString(item:AnyClass) -> String { +func toString(_ item:AnyClass) -> String { return "\(item)" } @@ -20,35 +20,35 @@ class MockingjaySessionTests: XCTestCase { } func testEphemeralSessionConfigurationIncludesProtocol() { - let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration() + let configuration = URLSessionConfiguration.ephemeral let protocolClasses = (configuration.protocolClasses!).map(toString) XCTAssertEqual(protocolClasses.first!, "MockingjayProtocol") } func testDefaultSessionConfigurationIncludesProtocol() { - let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() + let configuration = URLSessionConfiguration.default let protocolClasses = (configuration.protocolClasses!).map(toString) XCTAssertEqual(protocolClasses.first!, "MockingjayProtocol") } func testURLSession() { - let expectation = expectationWithDescription("MockingjaySessionTests") + let expectation = self.expectation(description: "MockingjaySessionTests") let stubbedError = NSError(domain: "Mockingjay Session Tests", code: 0, userInfo: nil) - stub(everything, builder: failure(stubbedError)) + stub(everything, failure(stubbedError)) - let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() - let session = NSURLSession(configuration: configuration) + let configuration = URLSessionConfiguration.default + let session = URLSession(configuration: configuration) - session.dataTaskWithURL(NSURL(string: "https://httpbin.org/")!) { data, response, error in - dispatch_async(dispatch_get_main_queue()) { + session.dataTask(with: URL(string: "https://httpbin.org/")!, completionHandler: { data, response, error in + DispatchQueue.main.async { XCTAssertNotNil(error) - XCTAssertEqual(error?.domain, "Mockingjay Session Tests") + XCTAssertEqual((error as? NSError)?.domain, "Mockingjay Session Tests") expectation.fulfill() } - }.resume() + }) .resume() - waitForExpectationsWithTimeout(5) { error in + waitForExpectations(timeout: 5) { error in XCTAssertNil(error, "\(error)") } } diff --git a/URITemplate b/URITemplate index afdf823..fc3c414 160000 --- a/URITemplate +++ b/URITemplate @@ -1 +1 @@ -Subproject commit afdf8236adb47172def94f78335500cec10b6db3 +Subproject commit fc3c414a412b4be83f413d1d18ee44404db736aa From 2dd1ff3fb3ed30ed422ed6c9f8d095d67dbfcfd5 Mon Sep 17 00:00:00 2001 From: Stuart Lynch Date: Wed, 21 Sep 2016 19:54:30 +0100 Subject: [PATCH 2/2] Fixed SteamContent support in Swift 3.0 (#64) * Added support for URLSession in tests * Fix a few range bugs, tests now pass * Restore xcodeproj file * Readded URITemplate import * Fix bug in Content-Range header --- Mockingjay/MockingjayProtocol.swift | 8 ++- .../MockingjayAsyncProtocolTests.swift | 8 ++- MockingjayTests/MockingjayProtocolTests.swift | 58 +++++++++++++++---- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/Mockingjay/MockingjayProtocol.swift b/Mockingjay/MockingjayProtocol.swift index e776584..4be4db6 100644 --- a/Mockingjay/MockingjayProtocol.swift +++ b/Mockingjay/MockingjayProtocol.swift @@ -148,7 +148,7 @@ public class MockingjayProtocol: URLProtocol { return } - let subdata = data.subdata(in: offset ..< offset) + let subdata = data.subdata(in: offset ..< (offset + length)) self.client?.urlProtocol(self, didLoad: subdata) Thread.sleep(forTimeInterval: 0.01) self.download(data, fromOffset: offset + length, withMaxLength: maxLength) @@ -163,7 +163,7 @@ public class MockingjayProtocol: URLProtocol { Int(str)! }) let loc = range[0] - let length = range[1] - loc + 1 + let length = range[1] + 1 return loc ..< length } @@ -175,13 +175,15 @@ public class MockingjayProtocol: URLProtocol { client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) return } + + let fullLength = data.count data = data.subdata(in: range) //Attach new headers to response if let r = response as? HTTPURLResponse { var header = r.allHeaderFields as! [String:String] header["Content-Length"] = String(data.count) - header["Content-Range"] = "bytes \(range.lowerBound)-\(range.upperBound)/\(range.lowerBound + range.upperBound)" + header["Content-Range"] = "bytes \(range.lowerBound)-\(range.upperBound)/\(fullLength)" response = HTTPURLResponse(url: r.url!, statusCode: r.statusCode, httpVersion: nil, headerFields: header)! } diff --git a/MockingjayTests/MockingjayAsyncProtocolTests.swift b/MockingjayTests/MockingjayAsyncProtocolTests.swift index 1d8aa3e..555e56d 100644 --- a/MockingjayTests/MockingjayAsyncProtocolTests.swift +++ b/MockingjayTests/MockingjayAsyncProtocolTests.swift @@ -105,8 +105,8 @@ class MockingjayAsyncProtocolTests: XCTestCase, URLSessionDataDelegate { let dataTask = urlSession.dataTask(with: request) dataTask.resume() - let mutableData = NSMutableData() - while mutableData.length < length { + var mutableData = Data() + while mutableData.count < length { let expectation = self.expectation(description: "testProtocolCanReturnedDataInChunks") self.didReceiveDataHandler = { (session: Foundation.URLSession, dataTask: URLSessionDataTask, data: Data) in mutableData.append(data) @@ -114,7 +114,9 @@ class MockingjayAsyncProtocolTests: XCTestCase, URLSessionDataDelegate { } waitForExpectations(timeout: 2.0, handler: nil) } -// XCTAssertEqual(mutableData, data.subdata(in: NSMakeRange(50000, length))) + + let correctData = data.subdata(in: 50000 ..< (50000 + length)) + XCTAssertEqual(mutableData, correctData) } // MARK: NSURLSessionDataDelegate diff --git a/MockingjayTests/MockingjayProtocolTests.swift b/MockingjayTests/MockingjayProtocolTests.swift index 8320c9d..409ecea 100644 --- a/MockingjayTests/MockingjayProtocolTests.swift +++ b/MockingjayTests/MockingjayProtocolTests.swift @@ -12,6 +12,14 @@ import Mockingjay class MockingjayProtocolTests : XCTestCase { + + var urlSession:URLSession! + + override func setUp() { + super.setUp() + urlSession = URLSession(configuration: URLSessionConfiguration.default) + } + override func tearDown() { super.tearDown() MockingjayProtocol.removeAllStubs() @@ -49,17 +57,23 @@ class MockingjayProtocolTests : XCTestCase { } var response: URLResponse? - var error: NSError? + var error:Error? var data: Data? = nil - do { - data = try NSURLConnection.sendSynchronousRequest(request, returning: &response) - } catch let error1 as NSError { - error = error1 + + let expectation = self.expectation(description: "testProtocolReturnsErrorWithRegisteredStubError") + let dataTask = urlSession.dataTask(with: request) { (d, r, e) in + response = r + data = d + error = e + expectation.fulfill() } - + dataTask.resume() + waitForExpectations(timeout: 2.0, handler: nil) + XCTAssertNil(response) XCTAssertNil(data) - XCTAssertEqual(error!.domain, "MockingjayTests") } + XCTAssertNotNil(error) + } func testProtocolReturnsResponseWithRegisteredStubError() { let request = URLRequest(url: URL(string: "https://kylefuller.co.uk/")!) @@ -71,13 +85,25 @@ class MockingjayProtocolTests : XCTestCase { }) { (request) -> (Response) in return Response.success(stubResponse, .content(stubData)) } - + var response:URLResponse? - let data = try? NSURLConnection.sendSynchronousRequest(request, returning: &response) + var data:Data? + var error:Error? + + let expectation = self.expectation(description: "testProtocolReturnsResponseWithRegisteredStubError") + let dataTask = urlSession.dataTask(with: request) { (d, r, e) in + response = r + data = d + error = e + expectation.fulfill() + } + dataTask.resume() + waitForExpectations(timeout: 2.0, handler: nil) XCTAssertEqual(response?.url, stubResponse.url!) XCTAssertEqual(response?.textEncodingName, "utf-8") XCTAssertEqual(data, stubData) + XCTAssertNil(error) } func testProtocolReturnsResponseWithLastRegisteredMatchinbgStub() { @@ -99,11 +125,23 @@ class MockingjayProtocolTests : XCTestCase { } var response:URLResponse? - let data = try? NSURLConnection.sendSynchronousRequest(request, returning: &response) + var data:Data? + var error:Error? + + let expectation = self.expectation(description: "testProtocolReturnsResponseWithRegisteredStubError") + let dataTask = urlSession.dataTask(with: request) { (d, r, e) in + response = r + data = d + error = e + expectation.fulfill() + } + dataTask.resume() + waitForExpectations(timeout: 2.0, handler: nil) XCTAssertEqual(response?.url, stubResponse.url!) XCTAssertEqual(response?.textEncodingName, "utf-8") XCTAssertEqual(data, stub2Data) + XCTAssertNil(error) } }