如何在Swift中单元测试抛出函数?

时间:2015-09-30 07:30:54

标签: xcode swift unit-testing

如何测试Swift 2.0中的函数是否抛出?如何断言抛出了正确的ErrorType

5 个答案:

答案 0 :(得分:53)

EDIT: Updated the code for Swift 4.1.

Here's the latest Swift version of Fyodor Volchyok's answer who used XCTAssertThrowsError:

    enum MyError: Error {
        case someExpectedError
        case someUnexpectedError
    }

    func functionThatThrows() throws {
        throw MyError.someExpectedError
    }

    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            XCTAssertEqual(error as! MyError, MyError.someExpectedError)
        }
    }

If your Error enum has associated values, you can either have your Error enum conform to Equatable, or use the if case statement:

    enum MyError: Error, Equatable {
        case someExpectedError
        case someUnexpectedError
        case associatedValueError(value: Int)
    }

    func functionThatThrows() throws {
        throw MyError.associatedValueError(value: 10)
    }

    // Equatable pattern: simplest solution if you have a simple associated value that can be tested inside 1 XCTAssertEqual
    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            XCTAssertEqual(error as! MyError, MyError.associatedValueError(value: 10))
        }
    }

    // if case pattern: useful if you have one or more associated values more or less complex (struct, classes...)
    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            guard case MyError.associatedValueError(let value) = error else {
                return XCTFail()
            }

            XCTAssertEqual(value, 10)
            // if you have several values or if they require more complex tests, you can do it here
        }
    }

答案 1 :(得分:18)

至少Xcode 7.3(可能更早)你可以使用内置的XCTAssertThrowsError()

    XCTAssertThrowsError(try methodThatThrows())

如果测试期间没有任何内容,你会看到类似的内容:

enter image description here

如果要检查抛出的错误是否属于某种具体类型,可以使用errorHandler的{​​{1}}参数:

XCTAssertThrowsError()

答案 2 :(得分:9)

给出以下函数和声明:

enum SomeError: ErrorType {
    case FifthError
    case FirstError
}

func throwingFunction(x: Int) throws {
    switch x {
    case 1:
        throw SomeError.FirstError
    case 5:
        throw SomeError.FifthError
    default:
        return
    }
}

如果给函数5,则此函数将抛出FifthError,如果给出1,则抛出FirstError

要测试,成功运行单元测试的函数可能如下所示:

func testNotError() {
    guard let _ = try? throwingFunction(2) else {
        XCTFail("Error thrown")
        return
    }
}

let _也可以替换为任何其他名称,因此您可以进一步测试输出。

断言函数抛出,无论ErrorType单元测试如何:

func testError() {
    if let _ = try? throwingFunction(5) {
        XCTFail("No error thrown")
        return
    }
}

如果您想使用ErrorType语句测试特定的do-catch。与其他语言相比,这不是最佳方式。

你必须确保你......

    {li> returncatch中找到正确的ErrorType 所有其他XCTFail()
  • returncatch 如果没有执行XCTFail(),则
  • catch

鉴于此要求,测试用例可能如下所示:

func testFifthError() {
    do {
        try throwingFunction(5)
    } catch SomeError.FifthError {
        return
    } catch {
        XCTFail("Wrong error thrown")
        return
    }
    XCTFail("No error thrown")
}

答案 3 :(得分:0)

Swift 4.1错误抛出相关值的测试

enum ParseError: Error, Equatable {
    case unexpectedArgument(String)
}

func testWithNoSchemaButWithOneArgument() {
    XCTAssertThrowsError(try Args(withSchema: "", andArguments: ["-x"])) { error in
        XCTAssertEqual(error as? ParseError, ParseError.unexpectedArgument("Argument(s) -x unexpected."))
    }
}

答案 4 :(得分:0)

您可以使用此功能:

func XCTAssertThrowsError<T, E: Error & Equatable>(
  _ expression: @autoclosure () throws -> T,
  error: E,
  in file: StaticString = #file,
  line: UInt = #line
  ) {
  var thrownError: Error?
  XCTAssertThrowsError(
    try expression(),
    file: file,
    line: line) {
      thrownError = $0
  }

  XCTAssertTrue(
    thrownError is E,
    "Unexpected error type: \(type(of: thrownError))",
    file: file,
    line: line
  )

  XCTAssertEqual(
    thrownError as? E,
    error,
    file: file,
    line: line
  )
}

示例:

XCTAssertThrowsError(try funcThatThrowsSpecificError(), error: SpecificErrorEnum.someError)