How to unit test throwing functions in Swift? How to unit test throwing functions in Swift? xcode xcode

How to unit test throwing functions in Swift?


EDIT: Updated the code for Swift 4.1 (still valid with Swift 5.2)

Here's the latest Swift version of Fyodor Volchyok's answer who used XCTAssertThrowsError:

    enum MyError: Error {        case someExpectedError        case someUnexpectedError    }    func functionThatThrows() throws {        throw MyError.someExpectedError    }    func testFunctionThatThrows() {        XCTAssertThrowsError(try functionThatThrows()) { error in            XCTAssertEqual(error as! MyError, MyError.someExpectedError)        }    }

If your Error enum has associated values, you can either have your Error enum conform to Equatable, or use the if case statement:

    enum MyError: Error, Equatable {        case someExpectedError        case someUnexpectedError        case associatedValueError(value: Int)    }    func functionThatThrows() throws {        throw MyError.associatedValueError(value: 10)    }    // Equatable pattern: simplest solution if you have a simple associated value that can be tested inside 1 XCTAssertEqual    func testFunctionThatThrows() {        XCTAssertThrowsError(try functionThatThrows()) { error in            XCTAssertEqual(error as! MyError, MyError.associatedValueError(value: 10))        }    }    // if case pattern: useful if you have one or more associated values more or less complex (struct, classes...)    func testFunctionThatThrows() {        XCTAssertThrowsError(try functionThatThrows()) { error in            guard case MyError.associatedValueError(let value) = error else {                return XCTFail()            }            XCTAssertEqual(value, 10)            // if you have several values or if they require more complex tests, you can do it here        }    }


At least of Xcode 7.3 (maybe earlier) you could use built-in XCTAssertThrowsError():

XCTAssertThrowsError(try methodThatThrows())

If nothing is thrown during test you'll see something like this:

enter image description here

If you want to check if thrown error is of some concrete type, you could use errorHandler parameter of XCTAssertThrowsError():

enum Error: ErrorType {    case SomeExpectedError    case SomeUnexpectedError}func functionThatThrows() throws {    throw Error.SomeExpectedError}XCTAssertThrowsError(try functionThatThrows(), "some message") { (error) in    XCTAssertEqual(error as? Error, Error.SomeExpectedError)}


Given the following functions and declarations:

enum SomeError: ErrorType {    case FifthError    case FirstError}func throwingFunction(x: Int) throws {    switch x {    case 1:        throw SomeError.FirstError    case 5:        throw SomeError.FifthError    default:        return    }}

This function will throw a FifthError if 5 is given to the function and FirstError if 1 is given.

To test, that a function successfully runs the unit test could look as follows:

func testNotError() {    guard let _ = try? throwingFunction(2) else {        XCTFail("Error thrown")        return    }}

The let _ may also be replaced by any other name, so you can further test the output.

To assert that a function throws, no matter what ErrorType the unit test could look like this:

func testError() {    if let _ = try? throwingFunction(5) {        XCTFail("No error thrown")        return    }}

If you want to test for a specific ErrorType it's done with a do-catch-statement. This is not the best way compared to other languages.

You have to make sure that you...

  • return in the catch for the correct ErrorType
  • XCTFail() and return for all other catch
  • XCTFail() if no catch is executed

Given this requirements a test case could look like this:

func testFifthError() {    do {        try throwingFunction(5)    } catch SomeError.FifthError {        return    } catch {        XCTFail("Wrong error thrown")        return    }    XCTFail("No error thrown")}