我想为一个带有闭包的函数创建一个测试,它会抛出一个错误。进行此测试的最佳做法是什么?
Credential.swift
WITH pcd AS (
SELECT *
FROM ig_Dimension..Profit_Center_Dimension pcd
WHERE (
OR (pcd.profit_center_id = '13' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = 14 AND csd.num_covers >= 10) -- is it an integer? or not?
OR (pcd.profit_center_id = '26' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = '49' AND csd.num_covers >= 15)
OR (pcd.profit_center_id = '57' AND csd.num_covers >= 10)
OR (pcd.profit_center_id = '74' AND csd.num_covers >= 15)
OR (pcd.profit_center_id = '77' AND csd.num_covers > 8)
OR (pcd.profit_center_id = 90 AND csd.num_covers >= 10) -- is it an integer? or not?
OR (pcd.profit_center_id = 98 AND csd.num_covers >= 8) -- is it an integer? or not?
OR (pcd.profit_center_id = '194' AND csd.num_covers >= 10)
OR (pcd.profit_center_id IN ('20', '21', '22', '200') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('40', '41', '42', '43') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('60', '61', '62', '63', '64', '65') AND csd.num_covers > 16)
OR (pcd.profit_center_id IN ('74', '101') AND csd.num_covers >= 10)
OR (pcd.profit_center_id IN ('86', '68') AND csd.num_covers >= 8)
OR (pcd.profit_center_id IN ('96', '98', '99') AND csd.num_covers >= 10)
)
AND pcd.ent_id = 1
)
SELECT
DATEPART(yyyy, csd.tendered_date_time) AS 'Year'
, DATEPART(mm, csd.tendered_date_time) AS 'Month'
, pcd.[Profit Centre]
, pcm.profit_center_name AS 'Profit Centre'
, pcd.profit_center_id
, COUNT(csd.num_covers)
FROM ig_business..Check_Sales_Detail csd
INNER JOIN pcd ON pcd.profit_center_dim_id = csd.profit_center_dim_id
INNER JOIN it_cfg..Profit_Center_Master pcm ON pcm.profit_center_id = pcd.profit_center_id
AND pcm.ent_id = 1
GROUP BY GROUPING SETS
( DATEPART(yyyy, csd.tendered_date_time) AS 'Year'
, DATEPART(mm, csd.tendered_date_time) AS 'Month'
, pcd.[Profit Centre]
, pcm.profit_center_name AS 'Profit Centre'
, pcd.profit_center_id
)
SignUpError.swift
class Credential {
let email: String
let password: String
init(email: String, password: String) {
self.email = email
self.password = password
}
}
FirebaseController.swift
enum SignUpError: Error {
case other(error: Error)
case userAlreadyExist
}
FirebaseControllerTests.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
})
}
}
答案 0 :(得分:0)
XCT提供XCTAssertNoThrow
和XCTAssertThrowsError
来明确断言抛出或不抛出异常(更多内容,例如here)。
例如:XCTAssertNoThrow(try inner())
但是,如果您对表达式的结果更感兴趣(如在您的情况下返回的user
)和期望那么该调用不应该抛出,您也可以忽略这些断言函数,而是使用try?
和任何" normal"断言(例如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
}