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

Bar*_*zyk 11 error-handling unit-testing swift2

这是我的方法定义:

func isValidForMode(mode: DBFindViewControllerMode) throws -> Bool { }
Run Code Online (Sandbox Code Playgroud)

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

XCTAssertTrue(try! searchOptionsManager.isValidForMode(.Address))
Run Code Online (Sandbox Code Playgroud)

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

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

以下是我的尝试:

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

但它失败了,因为:

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

zrz*_*zka 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
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以用它XCTAssertEqual:

func testExample() {
  do {
    try isValid()
  }
  catch let e as DBError {
    XCTAssertEqual(e, DBError.CannotBeEmpty(message: "Street"))
  }
  catch {
    XCTFail("Wrong error")
  }
}
Run Code Online (Sandbox Code Playgroud)

或者创建自己的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
  }
}
Run Code Online (Sandbox Code Playgroud)

和:

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() }
    }

}
Run Code Online (Sandbox Code Playgroud)


awp*_*wph 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

无需遵守 Equatable