在Swift中单元测试fatalError

前端之家收集整理的这篇文章主要介绍了在Swift中单元测试fatalError前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何在 Swift中执行fatalError代码路径的单元测试?

例如,我有以下swift代码

func divide(x: Float,by y: Float) -> Float {

    guard y != 0 else {
        fatalError("Zero division")
    }

    return x / y
}

当y = 0时,我想单位测试的情况.

注意,我想使用fatalError不是任何其他断言功能.

这个想法是用自己的内置fatalError函数替换,在单元测试的执行期间被替换,以便您在其中运行单元测试断言.

然而,棘手的部分是fatalError是@noreturn,所以你需要用一个永远不会返回的函数来覆盖它.

覆盖fatalError

仅在您的应用程序目标中(不要添加到单元测试目标):

// overrides Swift global `fatalError`
@noreturn func fatalError(@autoclosure message: () -> String = "",file: StaticString = __FILE__,line: UInt = __LINE__) {
    FatalErrorUtil.fatalErrorClosure(message(),file,line)
    unreachable()
}

/// This is a `noreturn` function that pauses forever
@noreturn func unreachable() {
    repeat {
        NSRunLoop.currentRunLoop().run()
    } while (true)
}

/// Utility functions that can replace and restore the `fatalError` global function.
struct FatalErrorUtil {

    // Called by the custom implementation of `fatalError`.
    static var fatalErrorClosure: (String,StaticString,UInt) -> () = defaultFatalErrorClosure

    // backup of the original Swift `fatalError`
    private static let defaultFatalErrorClosure = { Swift.fatalError($0,file: $1,line: $2) }

    /// Replace the `fatalError` global function with something else.
    static func replaceFatalError(closure: (String,UInt) -> ()) {
        fatalErrorClosure = closure
    }

    /// Restore the `fatalError` global function back to the original Swift implementation
    static func restoreFatalError() {
        fatalErrorClosure = defaultFatalErrorClosure
    }
}

延期

将以下扩展名添加到您的单元测试目标:

extension XCTestCase {
    func expectFatalError(expectedMessage: String,testcase: () -> Void) {

        // arrange
        let expectation = expectationWithDescription("expectingFatalError")
        var assertionMessage: String? = nil

        // override fatalError. This will pause forever when fatalError is called.
        FatalErrorUtil.replaceFatalError { message,_,_ in
            assertionMessage = message
            expectation.fulfill()
        }

        // act,perform on separate thead because a call to fatalError pauses forever
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED,0),testcase)

        waitForExpectationsWithTimeout(0.1) { _ in
            // assert
            XCTAssertEqual(assertionMessage,expectedMessage)

            // clean up 
            FatalErrorUtil.restoreFatalError()
        }
    }
}

测试用例

class TestCase: XCTestCase {
    func testExpectPreconditionFailure() {
        expectFatalError("boom!") {
            doSomethingThatCallsFatalError()
        }
    }
}

我从这篇文章中得到了关于单元测试断言和前提条件的想法:
Testing assertion in Swift

猜你在找的Swift相关文章