2015-07-22 12 views
11

To jest moja definicja metoda:Jak przetestować metodę, która zgłasza błąd w Swift 2?

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

Teraz mogę to sprawdzić w prosty sposób, ponieważ wiem, że to NIE zgłasza błąd:

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

Ale co, jeśli wiem, że rzuty metodami?

Najlepszym rozwiązaniem byłoby XCTAssertThrows(), ale to nie jest :-)

Poniżej moja próba:

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

Ale to się nie powiedzie, ponieważ:

Cannot find an overload for XCTAssertEqual that accepts an argument list of type (DBErrorType, DBErrorType)

Odpowiedz

17

DodaĂ DBError zgodny 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 
    } 
} 

I wtedy można go używać w XCTAssertEqual:

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

lub tworzyć własne 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 
    } 
} 

I:

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

} 
2

najlepszym rozwiązaniem do tej pory znalazłem:

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

W ten sposób można sprawdzić, czy wyjątek jest rzeczywiście zgłaszany, ale nie można sprawdzić, jaki wyjątek został zgłoszony.

+0

try nie rzuca wyjątkiem, ale błędem. catch nie obsługuje wyjątków, ale błędy. To nie są wyjątki. – robertvojta

+1

Całkowicie się zgadzam, ale byłoby miło, gdyby Apple to przyznał! Jest zrozumiałe, że ludzie wpadają w zakłopotanie, gdy metody w Fundacji zawodzą z błędami, takimi jak 'failed: caught 'NSInvalidArgumentException" ', co brzmi jak złapało wyjątek do mnie. – Sam

-1

Oto przykład, który będzie zrozumieć try-catch to sprawdzić poniżej kod

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

nadzieję, że rozumiesz

5

Albo po prostu użyć opcjonalnego 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) 
    } 
} 

Nie trzeba odpowiadać Equatable

1

Oto @robertvojta odpowiedź z kilku modyfikacji dla Xcode 9 i 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") 
     } 
    } 
} 

Zastosowanie:

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

Jeśli wiedzieć, że funkcja zgłasza błąd, powinieneś także upewnić się, że nie uda ci się, jeśli błąd nie zostanie zgłoszony.

mam modyfikowania odpowiedzi od @robertvojta i @ Vadim-Buławina tutaj:

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

Zastosowanie:

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) 
} 
+0

Zgadzam się, niezły chwyt –

Powiązane problemy