Skip to content

Instantly share code, notes, and snippets.

@ytyubox
Last active July 4, 2022 10:12
Show Gist options
  • Save ytyubox/89990452142f78a832b16d05600ade18 to your computer and use it in GitHub Desktop.
Save ytyubox/89990452142f78a832b16d05600ade18 to your computer and use it in GitHub Desktop.
extension Result {
func tryMap<T>(_ transform:(Success) throws -> T) -> Result<T, Swift.Error> {
switch self {
case let .success(success):
do {
return .success(try transform(success))
} catch {
return .failure(error)
}
case let .failure(failure):
return .failure(failure)
}
}
}
import XCTest
class ResultTryMapTests: XCTestCase {
private typealias Mapper<Input, Output> = (Input) throws -> Output
func testTryMapSouldSuccesIfSuccessfullyTransform() throws {
let alwaysSuccessMapper: Mapper<Int, String> = { _ in "any text" }
let sut = Result<Int, Error>.success(1)
let result = try XCTUnwrap(try? sut.tryMap(alwaysSuccessMapper).get())
XCTAssertEqual(result, "any text")
}
func testTryMapSouldFailureWithNewErrorIfFailsTransform() throws {
let alwaysThrowsMapper: Mapper<Int, String> = { _ in throw AnyError.anyFailure }
let sut = Result<Int, Error>.success(1)
let result = sut.tryMap(alwaysThrowsMapper)
XCTAssertThrowsError(try result.get()) {
error in
let anyError = error as? AnyError
XCTAssertNotNil(anyError)
XCTAssertEqual(anyError, .anyFailure)
}
}
func testTryMapSouldFailureWithOldErrorIfResultAlreadyAFailure() throws {
let alwaysThrowsMapper: Mapper<Int, String> = { _ in throw AnyError.anyFailure }
let sut = Result<Int, Error>.failure(AnyError.originalFailure)
let result = sut.tryMap(alwaysThrowsMapper)
XCTAssertThrowsError(try result.get()) {
error in
let anyError = error as? AnyError
XCTAssertNotNil(anyError)
XCTAssertEqual(anyError, .originalFailure)
}
}
func testTryMapWillExcuteTransformOnlyOnceIfResultisASuccess() throws {
var captured = [Int]()
let alwaysSuccessMapper: Mapper<Int, String> = { input in
captured.append(input)
return ""
}
let sut = Result<Int, Error>.success(0)
_ = sut.tryMap(alwaysSuccessMapper)
XCTAssertEqual(captured, [0])
}
func testTryMapWillExcuteTransformOnlyOnceIfResultAlreadyAFailure() throws {
var captured = [Int]()
let alwaysSuccessMapper: Mapper<Int, String> = { input in
captured.append(input)
return ""
}
let sut = Result<Int, Error>.failure(AnyError.originalFailure)
_ = sut.tryMap(alwaysSuccessMapper)
XCTAssertTrue(captured.isEmpty)
}
func testTryMapWillExcuteTransformOnlyOnceIfResultAlreadyASuccessOnTransformIsSuccess() throws {
var captured = [Int]()
let alwaysSuccessMapper: Mapper<Int, String> = { input in
captured.append(input)
return ""
}
let sut = Result<Int, Error>.success(0)
_ = sut.tryMap(alwaysSuccessMapper)
XCTAssertEqual(captured, [0])
}
func testTryMapWillExcuteTransformOnlyOnceIfResultAlreadyASuccessOnTransformIsThrows() throws {
var captured = [Int]()
let alwaysThrowsMapper: Mapper<Int, String> = { input in
captured.append(input)
throw AnyError.anyFailure
}
let sut = Result<Int, Error>.success(0)
_ = sut.tryMap(alwaysThrowsMapper)
XCTAssertEqual(captured, [0])
}
// MARK: - helper
private enum AnyError: Error {
case anyFailure
case originalFailure
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment