【问题标题】:Swift unit test throwing function from inside a closure从闭包内部的 Swift 单元测试抛出函数
【发布时间】:2018-06-24 17:52:57
【问题描述】:

我想为带有引发错误的闭包的函数创建一个测试。进行此测试的最佳做法是什么?

凭据.swift

class Credential {
    let email: String
    let password: String

    init(email: String, password: String) {
        self.email = email
        self.password = password
    }
} 

SignUpError.swift

enum SignUpError: Error {
    case other(error: Error)
    case userAlreadyExist
}

FirebaseController.swift

typealias SignUpResult = (_ inner: () throws -> RebloodUser) -> Void
func signUp(_ credential: RebloodCredential, completionHandler: @escaping SignUpResult) {
    self.auth.createUser(withEmail: credential.email, password: credential.password) { (user: User?, error: Error?) in

        guard let user = user, error == nil else {
            completionHandler({ () -> RebloodUser in
                throw SignUpError.other(error: error!)
            })
            return
        }


        completionHandler({ () -> RebloodUser in
            let rebloodUser = RebloodUser(firebaseIdentifier: user.uid)
            return rebloodUser
        })

    }
}   

FirebaseControllerTests.swift

let controller = FirebaseController()
let credential = Credential(email: "address@email.com", password: "Password1234")

func testControllerCanSignUp() {
    self.controller.signUp(self.credential) { (inner: () throws -> RebloodUser) -> Void in
        do {
            let user = try inner()
            XCTAssertNotNil(user.firebaseIdentifier)
            return
        } catch SignUpError.userAlreadyExist {
            return
        } catch {
            XCTFail("Wrong error thrown")
        }
    }
}

【问题讨论】:

    标签: ios swift unit-testing firebase error-handling


    【解决方案1】:

    XCT 提供 XCTAssertNoThrowXCTAssertThrowsError 用于显式断言抛出或不抛出异常(更多信息,例如 here)。

    例如:XCTAssertNoThrow(try inner())

    但是,如果您对表达式的结果更感兴趣(如在您的情况下返回的user)并且期望调用无论如何都不应该抛出,您也可以忽略这些断言函数,而是使用try? 和任何“正常”断言(例如XCTAssertEqual);如果意外抛出异常,测试仍然会中断,因为在这种情况下,表达式将评估为 nil 并且比较断言将失败(除非您的测试期望 nil 作为正确的结果,在这种情况下事情会变得更加复杂和您必须明确检查是否没有引发异常。)请注意,使用此代码,您将不知道测试是由于异常还是由于返回值无效而失败。

    例如:XCTAssertNotNil(try? inner().firebaseIdentifier)

    注意也就是说,如果您不介意多写几行,那么您实现期望测试的方式也很好,并且肯定比断言方法更灵活.


    对您的测试的另一个提示:假设FirebaseController.auth.createUser 是一个异步方法,您应该使用 XCT 期望让测试等到回调被调用:

    func testControllerCanSignUp() {
        let exp = expectation(description: "callback called") // create the expectation
        controller.signUp(self.credential) { (inner: () throws -> RebloodUser) -> () in
            XCTAssertNotNil(try? inner().firebaseIdentifier)
            exp.fulfill() // tell the test that your expectation was fulfilled
        }
        waitForExpectations(timeout: 1, handler: nil) // let the test wait for up to one second to give your async code the chance to complete
    }
    

    【讨论】:

    • 谢谢@dr_barto,有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 2019-10-21
    相关资源
    最近更新 更多