Mock 可以避免我們在寫單元測試的過程中不產(chǎn)生臟數(shù)據(jù)淘捡,還有如果你需要測試的方法中包含網(wǎng)絡(luò)請求的時候搁吓,你無法確定網(wǎng)絡(luò)請求的穩(wěn)定性俐填,測試次數(shù)越多,失敗的可能性就越高趟径,就如下面這段網(wǎng)絡(luò)請求的代碼,我們就需要對請求進(jìn)行Mock癣防。
func requestXingShuLin() {
let session = URLSession()
let url = URL(string: "http://www.xingshulin.com")!
let task = session.dataTask(with: url) { (data, _, _) -> Void in
if let data = data {
let string = String(data: data, encoding: String.Encoding.utf8)
print(string)
}
}
task.resume()
}
在Objective-C 中蜗巧,我們可以使用OCMock簡單的實現(xiàn)Mock,從技術(shù)上講蕾盯,你也可以在Swift 中也可以使用OCMock幕屹,但是有很嚴(yán)格的限制,并且功能有限级遭,因為OCMock是利用反射在運行時改變類的類型香嗓,而Swift 大多時候是無法在運行時修改的,雖然你可以使用dynamic 來增加一些動態(tài)性装畅,但這是不推薦的靠娱,可能在以后Swift 也不會支持,因為Swift 是一個安全的編程語言掠兄。Swift目前也有一些可以實現(xiàn)Mock 的框架像云,如 Dobby、MockFive 蚂夕、SwiftMock 等迅诬。但我更傾向于自己來寫Mock。
我們可以使用Swift 中面向協(xié)議的思想來完成這次Mock婿牍。
我們先定義一個協(xié)議侈贷,并給URLSession 實現(xiàn)。
protocol URLSessionMockDelegate {
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask
}
extension URLSession: URLSessionMockDelegate {
}
class RequestTest: NSObject {
let session: URLSessionMockDelegate
let url: URL
init(session: URLSessionMockDelegate, url: URL) {
self.session = session
self.url = url
}
func requestXingShuLin(completeHandler: @escaping (_ success: Bool) -> ()) {
let url = URL(string: "https://www.xingshulin.com")!
let task = session.dataTask(with: url) { (data, _, _) -> Void in
if let data = data {
let string = String(data: data, encoding: String.Encoding.utf8)
print(string)
completeHandler(true)
} else {
completeHandler(false)
}
}
task.resume()
}
}
然后定義一個MockURLSession 實現(xiàn)URLSessionMockDelegate 協(xié)議等脂,實現(xiàn)其 dataTask 方法俏蛮。
func testRequest_Success() {
//Given
class MockURLSession: URLSessionMockDelegate {
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask {
if url == URL(string: "https://www.xingshulin.com")! {
completionHandler(Data(), nil, nil)
} else {
completionHandler(nil, nil, nil)
}
}
}
let mockSession = MockURLSession()
let url = URL(string: "https://www.xingshulin.com")!
let requestTest = RequestTest(session: mockSession, url: url)
//When
var status = false
requestTest.requestXingShuLin { (isSuccess) in
status = isSuccess
}
//Then
waitForExpectations(timeout: 0.5) { (error) in
XCTAssertTrue(status)
}
}
使用協(xié)議來實現(xiàn)Mock 也很簡單撑蚌。