如何测试在 Swift 2 中抛出错误的方法?
How to test method that throws error in Swift 2?
这是我的方法定义:
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"))
}
但是失败了,因为:
Cannot find an overload for XCTAssertEqual
that accepts an argument list of type (DBErrorType, DBErrorType)
到目前为止我找到的最佳解决方案是:
do {
try searchOptionsManager.isValidForMode(.Address)
XCTAssertTrue(false)
} catch {
XCTAssertTrue(true)
}
这种方式可以测试是否真的抛出了异常,但是无法判断抛出的是什么类型的异常。
让你的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() }
}
}
这是您将理解 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")
}
希望你明白
或者简单地使用可选的 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
这是@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)
}
如果您知道函数会抛出错误,那么您还应该确保在没有抛出错误的情况下失败。
我正在修改来自@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)
}
这是我的方法定义:
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"))
}
但是失败了,因为:
Cannot find an overload for
XCTAssertEqual
that accepts an argument list of type(DBErrorType, DBErrorType)
到目前为止我找到的最佳解决方案是:
do {
try searchOptionsManager.isValidForMode(.Address)
XCTAssertTrue(false)
} catch {
XCTAssertTrue(true)
}
这种方式可以测试是否真的抛出了异常,但是无法判断抛出的是什么类型的异常。
让你的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() }
}
}
这是您将理解 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")
}
希望你明白
或者简单地使用可选的 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
这是@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)
}
如果您知道函数会抛出错误,那么您还应该确保在没有抛出错误的情况下失败。
我正在修改来自@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)
}