Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test throwing functions in Swift?

How to test wether a function in Swift 2.0 throws or not? How to assert that the correct ErrorType is thrown?

like image 655
Fabio Poloni Avatar asked Sep 30 '15 07:09

Fabio Poloni


2 Answers

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         }     } 
like image 119
Ferschae Naej Avatar answered Sep 28 '22 23:09

Ferschae Naej


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) } 
like image 26
Fyodor Volchyok Avatar answered Sep 29 '22 01:09

Fyodor Volchyok