xcode 如何在 Swift 中对抛出函数进行单元测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32860338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 07:57:56  来源:igfitidea点击:

How to unit test throwing functions in Swift?

xcodeswiftunit-testing

提问by Fabio Poloni

How to test wether a function in Swift 2.0 throws or not? How to assert that the correct ErrorTypeis thrown?

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

回答by Ferschae Naej

EDIT: Updated the code for Swift 4.1(still valid with Swift 5.2)

编辑:更新了代码Swift 4.1(仍然有效Swift 5.2

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

这是Fyodor Volchyok 回答的最新 Swift 版本,他使用了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 Errorenum has associated values, you can either have your Errorenum conform to Equatable, or use the if casestatement:

如果您的Error枚举具有关联值,您可以让您的Error枚举符合Equatable,或使用以下if case语句:

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

回答by Fyodor Volchyok

At least of Xcode 7.3 (maybe earlier) you could use built-in XCTAssertThrowsError():

至少在 Xcode 7.3(可能更早)中,您可以使用 built-in XCTAssertThrowsError()

XCTAssertThrowsError(try methodThatThrows())

If nothing is thrown during test you'll see something like this:

如果在测试期间没有抛出任何内容,您将看到如下内容:

enter image description here

enter image description here

If you want to check if thrown error is of some concrete type, you could use errorHandlerparameter of XCTAssertThrowsError():

如果要检查抛出的错误是否属于某种具体类型,可以使用以下errorHandler参数XCTAssertThrowsError()

enum Error: ErrorType {
    case SomeExpectedError
    case SomeUnexpectedError
}

func functionThatThrows() throws {
    throw Error.SomeExpectedError
}

XCTAssertThrowsError(try functionThatThrows(), "some message") { (error) in
    XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}

回答by Fabio Poloni

Given the following functions and declarations:

给定以下函数和声明:

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

This function will throw a FifthErrorif 5 is given to the function and FirstErrorif 1 is given.

FifthError如果给函数 5 并且给定FirstError1,则此函数将抛出一个。

To test, that a function successfully runs the unit test could look as follows:

为了测试,一个函数成功运行单元测试可能如下所示:

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

The let _may also be replaced by any other name, so you can further test the output.

let _还可以通过任何其他名称代替,这样可以进一步测试输出。

To assert that a function throws, no matter what ErrorTypethe unit test could look like this:

断言一个函数抛出,不管ErrorType单元测试是什么样的:

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

If you want to test for a specific ErrorTypeit's done with a do-catch-statement. This is not the best way compared to other languages.

如果你想测试一个特定的ErrorType它是用 -do-catch语句完成的。与其他语言相比,这不是最好的方法。

You have to make sure that you...

你必须确保你...

  • returnin the catchfor the correct ErrorType
  • XCTFail()and returnfor all other catch
  • XCTFail()if no catchis executed
  • returncatch为了正确ErrorType
  • XCTFail()return所有其他catch
  • XCTFail()如果没有catch被执行

Given this requirements a test case could look like this:

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

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

回答by Declan McKenna

Swift 4.1 Error throwing Test for associated values

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

回答by Vitaliy Gozhenko

You can use this function:

您可以使用此功能:

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 = 
XCTAssertThrowsError(try funcThatThrowsSpecificError(), error: SpecificErrorEnum.someError)
} XCTAssertTrue( thrownError is E, "Unexpected error type: \(type(of: thrownError))", file: file, line: line ) XCTAssertEqual( thrownError as? E, error, file: file, line: line ) }

Example:

例子:

##代码##