Created
August 31, 2024 09:54
-
-
Save rhysm94/ad36db321f172b7c9e9ddbf60f0cca88 to your computer and use it in GitHub Desktop.
Demonstrates a protocol which can help with overriding protocol-witness style dependencies, adding expectations when called.
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
protocol Overrideable {} | |
extension Overrideable { | |
mutating func `override`<Input: Equatable, Output>( | |
method: WritableKeyPath<Self, @Sendable (Input) async throws -> Output>, | |
expectedInput: Input, | |
returning value: Output, | |
name: String | |
) { | |
let expectation = expectation(description: name) | |
let capturedMethod = self[keyPath: method] | |
self[keyPath: method] = { input in | |
if input == expectedInput { | |
expectation.fulfill() | |
return value | |
} else { | |
return try await capturedMethod(input) | |
} | |
} | |
} | |
} | |
extension Overrideable { | |
mutating func `override`<each Input: Equatable, Output>( | |
method: WritableKeyPath<Self, @Sendable (repeat each Input) async throws -> Output>, | |
expectedInput: (repeat each Input), | |
returning value: Output, | |
name: String | |
) { | |
let expectation = expectation(description: name) | |
let capturedMethod = self[keyPath: method] | |
// Cannot assign through subscript: 'self' is immutable | |
self[keyPath: method] = { (inputs: (repeat each Input)) in | |
let equal = isEqual(lhs: expectedInput, rhs: inputs) | |
if equal { | |
expectation.fulfill() | |
return value | |
} else { | |
// Cannot pass value pack expansion to non-pack parameter of type 'repeat each Input' | |
return try await capturedMethod(inputs) | |
} | |
} | |
} | |
} | |
private func isEqual<each Element: Equatable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool { | |
for (left, right) in repeat (each lhs, each rhs) { | |
guard left == right else { return false } | |
} | |
return true | |
} | |
// Substitute for XCTest expectation | |
struct Expectation { | |
var name: String | |
func fulfill() { | |
print("Fulfilled expectation \(name)") | |
} | |
} | |
func expectation(description: String) -> Expectation { | |
let expectation = Expectation(name: description) | |
print("Created expectation") | |
return expectation | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment