Skip to content

Instantly share code, notes, and snippets.

@oleksii-demedetskyi
Created April 14, 2016 17:41
Show Gist options
  • Save oleksii-demedetskyi/6a9d89e1c41fe09eeebe0cf0bc4ae6bf to your computer and use it in GitHub Desktop.
Save oleksii-demedetskyi/6a9d89e1c41fe09eeebe0cf0bc4ae6bf to your computer and use it in GitHub Desktop.
//: [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