Created
April 14, 2016 17:41
-
-
Save oleksii-demedetskyi/6a9d89e1c41fe09eeebe0cf0bc4ae6bf to your computer and use it in GitHub Desktop.
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
//: [Previous](@previous) | |
import Foundation | |
// One per function | |
final class Stub { | |
let name: String | |
let cmp: (AnyCall, AnyCall) -> Bool | |
init(name: String, cmp: (AnyCall, AnyCall) -> Bool) { | |
self.name = name | |
self.cmp = cmp | |
} | |
} | |
// One per function call | |
struct Call<T> { | |
let stub: Stub | |
let arguments: T | |
} | |
protocol AnyCall { | |
var stub: Stub { get } | |
var args: Any { get } | |
} | |
extension Call: AnyCall { | |
var args: Any { return arguments } | |
} | |
var calls = [] as [AnyCall] | |
func recordCall(call: AnyCall) { | |
calls.append(call) | |
} | |
func verifyCall(call: AnyCall) { | |
guard calls.count > 0 else { | |
print("Unexpected call: \(call)") | |
return | |
} | |
let expectedCall = calls.removeFirst() | |
// compare? | |
// 1) stub | |
guard call.stub === expectedCall.stub else { | |
print("Wrong call. Expect: [\(expectedCall.stub.name)]. Receive: [\(call.stub.name)]") | |
return | |
} | |
// 2) arguments | |
guard call.stub.cmp(expectedCall, call) else { | |
print("Wrong arguments for [\(call.stub.name)]. Expect: [\(expectedCall.args)]. Receive: [\(call.args)]") | |
return | |
} | |
} | |
// Context | |
var processCall: AnyCall -> () = { _ in } | |
// Build stubs. | |
func stub<T>(name: String, cmp: (T, T) -> Bool) -> (T -> ()) { | |
let stub = Stub(name: name) { expected, actual in | |
guard let expected = expected as? Call<T> else { fatalError() } | |
guard let actual = actual as? Call<T> else { fatalError() } | |
return cmp(expected.arguments, actual.arguments) | |
} | |
return { t in | |
processCall(Call(stub: stub, arguments: t)) | |
} | |
} | |
func stub<T: Equatable>(name: String) -> (T -> ()) { | |
return stub(name) { $0 == $1 } | |
} | |
func stub<T: Equatable>(name: String) -> (T? -> ()) { | |
return stub(name) { $0 == $1 } | |
} | |
func stub<T: Equatable>(name: String) -> ([T] -> ()) { | |
return stub(name) { $0 == $1 } | |
} | |
let showText = stub("show text") as String -> () | |
let showImage = stub("show image") as String -> () | |
// Context | |
func record(f: () -> ()) { | |
processCall = recordCall | |
f() | |
processCall = { _ in } | |
} | |
func verify(f: () -> ()) { | |
processCall = verifyCall | |
f() | |
processCall = { _ in } | |
} | |
struct View { | |
let showFirstName: String -> () | |
let showLastName: String -> () | |
let showImage: NSURL -> () | |
} | |
struct User { | |
let firstName: String | |
let lastName: String | |
let image: NSURL | |
} | |
class Presenter { | |
func present(user: User, inView view: View) { | |
view.showFirstName(user.firstName) | |
view.showLastName(user.lastName) | |
view.showImage(user.image) | |
} | |
} | |
let view = View( | |
showFirstName: stub("show first name"), | |
showLastName: stub("show last name"), | |
showImage: stub("show image")) | |
let user = User(firstName: "Alexey", lastName: "DAloG", image: NSURL(string:"http://text")!) | |
record { | |
Presenter().present(user, inView: view) | |
} | |
verify { | |
view.showFirstName("ALEXEY") | |
view.showLastName("DAloG") | |
view.showImage(NSURL(string:"http://text")!) | |
} | |
// TODO: Pack in a library. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment