Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Unit Testing ReactiveSwift streams with Assertions (idea by @andersio)
import ReactiveSwift
import XCTest
private let counterFailure: (Int, Int) -> String = { count, maxCount in
return "Counter is currently at \(count) which higher than the max \(maxCount)"
}
private let timeoutFailure = "Expectation timeout"
private let infoTemplate: (String, String, Int) -> String = { fileName, functionName, lineNumber in
return "➡️ filename: \(fileName)\n ➡️ functionName: \(functionName)\n ➡️ lineNumber: \(lineNumber)"
}
private let failureTemplate: (String, String) -> String = { value, info in
return """
\n❌❌❌❌❌
👉 \(value) 👈 \n \(info)
❌❌❌❌❌
"""
}
public extension SignalProducer where Error == Never {
func assertValues(
maxCount: Int = .max,
timeout: TimeInterval = 3,
fileName: String = #file,
functionName: String = #function,
lineNumber: Int = #line,
action: @escaping (Value, Int) -> Void
) {
let info = infoTemplate(fileName, functionName, lineNumber)
let expectation = XCTestExpectation(description: info)
expectation.expectedFulfillmentCount = maxCount
var _count = 1
self.startWithValues { value in
guard _count <= maxCount else {
XCTFail(failureTemplate(counterFailure(_count, maxCount), info))
expectation.fulfill()
return
}
action(value, _count)
expectation.fulfill()
_count += 1
}
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
switch result {
case .timedOut:
XCTFail(failureTemplate(timeoutFailure, info))
default:
break
}
}
}
public extension SignalProducer {
func assertResult(
maxCount: Int = .max,
timeout: TimeInterval = 3,
fileName: String = #file,
functionName: String = #function,
lineNumber: Int = #line,
action: @escaping (Result<Value, Error>, Int) -> Void
) {
let info = infoTemplate(fileName, functionName, lineNumber)
let expectation = XCTestExpectation(description: info)
expectation.expectedFulfillmentCount = maxCount
var _count = 1
self.startWithResult { result in
guard _count <= maxCount else {
XCTFail(failureTemplate(counterFailure(_count, maxCount), info))
expectation.fulfill()
return
}
action(result, _count)
expectation.fulfill()
_count += 1
}
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
switch result {
case .timedOut:
XCTFail(failureTemplate(timeoutFailure, info))
default:
break
}
}
func assertCompletion(
timeout: TimeInterval = 3,
fileName: String = #file,
functionName: String = #function,
lineNumber: Int = #line,
action: @escaping () -> Void
) {
let info = infoTemplate(fileName, functionName, lineNumber)
let expectation = XCTestExpectation(description: info)
self.startWithCompleted {
action()
expectation.fulfill()
}
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
switch result {
case .timedOut:
XCTFail(failureTemplate(timeoutFailure, info))
default:
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment