Created
October 16, 2020 21:06
-
-
Save frootloops/de256f714db0bdbde9499381e5dd83cd to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
public struct MockFunc<Input, Output> { | |
public var parameters: [Input] = [] | |
public var result: (Input) -> Output = { _ in fatalError() } | |
public init() {} | |
public init(result: @escaping (Input) -> Output) { | |
self.result = result | |
} | |
public var count: Int { | |
return parameters.count | |
} | |
public var called: Bool { | |
return !parameters.isEmpty | |
} | |
public var output: Output { | |
return result(input) | |
} | |
public var input: Input { | |
return parameters[count - 1] | |
} | |
public static func mock(for function: (Input) throws -> Output) -> MockFunc { | |
return MockFunc() | |
} | |
public mutating func call(with input: Input) { | |
parameters.append(input) | |
} | |
public mutating func callAndReturn(_ input: Input) -> Output { | |
call(with: input) | |
return output | |
} | |
} | |
// MARK: Syntactic Sugar | |
extension MockFunc { | |
public mutating func returns(_ value: Output) { | |
result = { _ in value } | |
} | |
public mutating func returns() where Output == Void { | |
result = { _ in () } | |
} | |
public mutating func returnsNil<T>() | |
where Output == Optional<T> { | |
result = { _ in nil } | |
} | |
public mutating func succeeds<T, Error>(_ value: T) | |
where Output == Result<T, Error> { | |
result = { _ in .success(value) } | |
} | |
public mutating func fails<T, Error>(_ error: Error) | |
where Output == Result<T, Error> { | |
result = { _ in .failure(error) } | |
} | |
} | |
extension MockFunc where Input == Void { | |
public mutating func call() { | |
parameters.append(()) | |
} | |
public mutating func callAndReturn() -> Output { | |
call(with: ()) | |
return output | |
} | |
} | |
public func beCalled<In, Out>() -> Predicate<MockFunc<In, Out>> { | |
return Predicate.define("be called", matcher: { expression, message -> PredicateResult in | |
guard let actual = try expression.evaluate() else { | |
return PredicateResult(status: .fail, message: message) | |
} | |
return PredicateResult(bool: actual.called, message: message) | |
}) | |
} | |
public func beCalled<In, Out>(count: Int) -> Predicate<MockFunc<In, Out>> { | |
let msg = "be called \(count) times" | |
return Predicate.define(msg) { expression, message -> PredicateResult in | |
guard let actual = try expression.evaluate() else { | |
return PredicateResult(status: .fail, message: message) | |
} | |
return PredicateResult( | |
bool: actual.count == count, | |
message: .expectedCustomValueTo(msg, "\(actual.count) times") | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment