如何在Swift 2中测试抛出错误的方法?

时间:2015-07-22 09:04:14

标签: unit-testing error-handling swift2

这是我的方法定义:

func isValidForMode(mode: DBFindViewControllerMode) throws -> Bool { }

现在我可以用简单的方式测试一下,因为我知道不要会抛出错误:

XCTAssertTrue(try! searchOptionsManager.isValidForMode(.Address))

但如果我知道该方法会抛出怎么办?

最佳解决方案是XCTAssertThrows(),但不是: - )

以下是我的尝试:

do {
    try searchOptionsManager.isValidForMode(.Address)
} catch let error {
    XCTAssertEqual(error as! DBErrorType, DBErrorType.CannotBeEmpty("Street"))
}

但它失败了,因为:

  

找不到接受XCTAssertEqual类型的参数列表的(DBErrorType, DBErrorType)的重载

5 个答案:

答案 0 :(得分:18)

DBError符合Equatable

enum DBError: ErrorType, Equatable {
  case CannotBeEmpty(message: String)
}

func ==(lhs: DBError, rhs: DBError) -> Bool {
  switch (lhs, rhs) {
    case (.CannotBeEmpty(let leftMessage), .CannotBeEmpty(let rightMessage)):
      return leftMessage == rightMessage
  }
}

然后您可以在XCTAssertEqual

中使用它
func testExample() {
  do {
    try isValid()
  }
  catch let e as DBError {
    XCTAssertEqual(e, DBError.CannotBeEmpty(message: "Street"))
  }
  catch {
    XCTFail("Wrong error")
  }
}

或者创建自己的XCTAssertThrows

enum DBError: ErrorType, Equatable {
  case CannotBeEmpty(message: String)
}

func ==(lhs: DBError, rhs: DBError) -> Bool {
  switch (lhs, rhs) {
    case (.CannotBeEmpty(let leftMessage), .CannotBeEmpty(let rightMessage)):
      return leftMessage == rightMessage
  }
}

func XCTAssertThrows<T: ErrorType where T: Equatable>(error: T, block: () throws -> ()) {
  do {
    try block()
  }
  catch let e as T {
    XCTAssertEqual(e, error)
  }
  catch {
    XCTFail("Wrong error")
  }
}

class TestsTests: XCTestCase {

    func testExample() {
      XCTAssertThrows(DBError.CannotBeEmpty(message: "Street")) { try isValid() }
    }

}

答案 1 :(得分:5)

或者只是使用可选的try

extension XCTestCase {
    func XCTAssertThrows(@autoclosure expression: () throws -> Void, _ message: String = "", file: String = __FILE__, line: UInt = __LINE__) {
        XCTAssert((try? expression()) == nil, message, file: file, line: line)
    }
}

无需符合Equatable

答案 2 :(得分:2)

到目前为止,我发现的最佳解决方案是:

do {
    try searchOptionsManager.isValidForMode(.Address)
    XCTAssertTrue(false)
} catch {
    XCTAssertTrue(true)
}

通过这种方式,您可以测试是否真的抛出了异常,但是您无法检查抛出的异常类型。

答案 3 :(得分:1)

这是@robertvojta的答案,对Xcode 9和Swift 3 - 4进行了几次修改:

extension XCTestCase {
    func XCTAssertThrows<ErrorType: Error, T>(expression: @autoclosure () throws -> T, error: ErrorType) where ErrorType: Equatable {
        do {
            _ = try expression()
        } catch let caughtError as ErrorType {
            XCTAssertEqual(caughtError, error)
        } catch {
            XCTFail("Wrong error")
        }
    }
}

用法:

enum APIError: LocalizedError {
    case cancelled

    public var errorDescription: String? {
        switch self {
        case .cancelled:
            return "The operation has been cancelled by user."
        }
    }
}

func testThatIsThrowsCancelledByUserError() {
    XCTAssertThrows(expression: try api.cancelLoginOperation(), error: APIError.cancelled)
}

答案 4 :(得分:-1)

以下是您将了解try-catch检查以下代码

的示例
func validateCredencials() throws {

guard username.characters.count > 0  && password.characters.count > 0 
else { throw EncryptionType.Empty }
    guard password.characters.count >= 5 else { throw EncryptionType.Short }
}
    do {
    try validateCredencials()
    }catch EncryptionType.Empty {
        print("password Empty")

    } catch EncryptionType.Short {
        print("Password too shoot")
    }catch {
        print("Some thing went Wrong")
    }

希望你明白