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

ux6nzvsh  于 2022-11-06  发布在  Swift
关注(0)|答案(6)|浏览(238)

这是我的方法定义:

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

现在我可以用一种简单的方法来测试它,因为我知道它DO NOT会抛出一个错误:

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

但是如果我知道这个方法会掷回呢?
最好的解决方案将是XCTAssertThrows(),但它不是:-)
下面是我的尝试:

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

但它失败了,因为:
找不到接受(DBErrorType, DBErrorType)类型的参数列表的XCTAssertEqual重载

mwkjh3gx

mwkjh3gx1#

使您的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() }
    }

}
nkkqxpd9

nkkqxpd92#

或者,只需使用可选的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

kxe2p93d

kxe2p93d3#

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

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

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

nwsw7zdq

nwsw7zdq4#

以下是@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)
}
hc8w905p

hc8w905p5#

如果您知道函数会抛出错误,那么您还应该确保在未抛出错误的情况下失败。
我在这里修改了来自@robertvojta和@vadim-bulavin的回答:

extension XCTestCase {
    func XCTAssertThrows<ErrorType: Error, T>(expression: @autoclosure () throws -> T, error: ErrorType) where ErrorType: Equatable {
        do {
            _ = try expression()
            XCTFail("No error thrown")
        } 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)
}
btqmn9zl

btqmn9zl6#

下面是一个示例,您将了解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")
    }

希望你能理解

相关问题