XCTAssertThrowsError 自定义 errorHandler 的奇怪行为

2024-01-08

在我的单元测试中,我有以下代码来检查抛出的错误是否属于预期类型。它是通过两个相同的语句完成的,其中之一无法编译:

    enum Error: ErrorType {
        case SomeExpectedError
        case SomeUnexpectedError
    }

    func functionThatThrows() throws {
        throw Error.SomeExpectedError
    }

    // 1) this compiles fine
    XCTAssertThrowsError(try functionThatThrows()) { (error) in
        switch error {
        case Error.SomeExpectedError: break
            //everything is fine
        case Error.SomeUnexpectedError: fallthrough
        default:
            XCTFail("Unexpected error thrown")
        }
    }

    // 2) doesn't compiles at all
    XCTAssertThrowsError(try functionThatThrows()) { (error) in
        XCTAssertEqual(error as? Error, Error.SomeExpectedError)
    }

第一条语句编译并工作正常,但第二条语句告诉我有两个错误:Errors thrown from here are not handled and Cannot convert value of type '(Error) -> Void' to expected argument type 'String'.

这段代码可能有什么问题?错误消息是什么意思?

我正在使用 Xcode 7.3 。


经过一番研究,我发现我的代码有两个问题:

1)似乎我的关闭已被考虑“隐晦地回归” https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID99因为它只包含一条可执行语句

2)编译器对我的语句感到困惑,因为 XCTAssertThows 接受另一个接受闭包的参数 - 它是@autoclosure _ message: () -> String

结果编译器认为我传递了消息闭包(恕我直言,令人困惑的设计决策 - 传递@自动关闭 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID543作为消息参数),当我实际传递 errorHandler 的闭包时。

解决方案很简单:

    // explicitly show closure returning type Void so that compiler couldn't
    // use it as message argument (which closure must return String)
    XCTAssertThrowsError(try functionThatThrows()) { (error) -> Void in
        XCTAssertEqual(error as? Error, Error.SomeExpectedError)
    }

    // explicitly show closure's argument type
    XCTAssertThrowsError(try functionThatThrows()) { (error: ErrorType) in
        XCTAssertEqual(error as? Error, Error.SomeExpectedError)
    }

    // use "message" parameter to preserve argument order
    XCTAssertThrowsError(try functionThatThrows(), "some message") { (error) in
        XCTAssertEqual(error as? Error, Error.SomeExpectedError)
    }

    // wrap executable line in "do {}". I guess it works because closure stops
    // being "implicitly returning" and now compiler treat it as () -> Void
    // which is expected type of errorHandler argument
    XCTAssertThrowsError(try functionThatThrows()) { (error) in
        do {
            XCTAssertEqual(error as? Error, Error.SomeExpectedError)
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XCTAssertThrowsError 自定义 errorHandler 的奇怪行为 的相关文章

随机推荐