XCTAssertThrowsError带有自定义errorHandler的奇怪行为 [英] XCTAssertThrowsError strange behavior with custom errorHandler

查看:152
本文介绍了XCTAssertThrowsError带有自定义errorHandler的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my unit test I have the following code that checks whether thrown error is of expected type. It is done with two identical statements one of which doesn't compile:

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

第一个语句可以编译并正常工作,但是第二个语句告诉我有两个错误:
无法处理从此处引发的错误无法转换类型‘(Error)->的值’无效到期望的参数类型字符串

First statement compiles and works fine, but seconds one says me that there are two errors: Errors thrown from here are not handled and Cannot convert value of type '(Error) -> Void' to expected argument type 'String'.

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

What could be wrong with this code? What do error messages mean?

我正在使用Xcode 7.3。

I am using Xcode 7.3 .

推荐答案

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

After a little research I found 2 problems with my code:

1)似乎我的闭包被认为是不合法地返回 ,因为它仅包含一个可执行语句

1) seems like my closure considered "Impilictly returning" because it contains only one executable statement

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

2) compiler was confused by my statement since XCTAssertThows accepts one more parameter that accepts closure - it's @autoclosure _ message: () -> String

结果是编译器认为我通过了消息的闭包(恕我直言,混淆了设计决策-传递了 @ autoclosure 作为消息参数),当我实际通过errorHandler的闭包时。

As a result compiler thought that I passed closure for message (IMHO confusing design decision - to pass @autoclosure as message argument), when I actually passed closure for 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)
        }
    }

这篇关于XCTAssertThrowsError带有自定义errorHandler的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆