As I am trying to learn TDD with iOS and Swift Development, I am following Pauls book Testing Swift, and tI have reached the part where he mocks networking and starts to implement test. I along side also am trying to do so but I am failing in the first test, could anybody point out why is my test failing.
The sample code in the book is testing dataTask
for URLSession
, but I am testing downloadTask
. Here goes the sample code
The source which is responsible for downloading a file from network.
import Foundation
public enum DownloadError: Error {
case responseCodeError
case fileError
}
public class NetworkInteractor {
var session: MockSession
var url: URL
public typealias DownloadCompletion = Result<URL, DownloadError>
public convenience init? (urlString: String) {
self.init(url: URL(string: urlString)!)
}
init(session: MockSession = URLSession.shared, url: URL) {
self.session = session
self.url = url
}
open func downloadFile(completion: @escaping(DownloadCompletion) -> Void) {
session.downloadTask(with: url) { downloadeURL, response, error in
if let _ = error {
completion(.failure(.responseCodeError)) // replace with appropriate error
}
if let response = response as? HTTPURLResponse, response.statusCode != 200 {
completion(.failure(.responseCodeError))
}
if let url = downloadeURL {
completion(.success(url))
}
}.resume()
}
}
The mock class,
import Foundation
// MARK:- Mock to help download
protocol MockSession {
func downloadTask(with url: URL, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask
}
class DataTaskMock: URLSessionDownloadTask {
var completionHandler: (URL?, URLResponse?, Error?) -> Void?
var resumeWasCalled: Bool = false
init(completionHandler: @escaping(URL?, URLResponse?, Error?)-> Void) {
self.completionHandler = completionHandler
}
override func resume() {
resumeWasCalled = true
completionHandler(nil, nil, nil)
}
}
extension URLSession: MockSession {}
class URLSessionMock: MockSession {
var lastURL: URL?
var downloadTask: DataTaskMock?
func downloadTask(with url: URL, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask {
let newDataTask = DataTaskMock(completionHandler: completionHandler)
lastURL = url
downloadTask = newDataTask
return newDataTask
}
}
The test class,
class StorableTests: XCTestCase {
public func testItLoadsURLCorrectly() {
let url = URL(string: "https://a-url.com")!
let session = URLSessionMock()
let interactor = NetworkInteractor(session: session, url: url)
let expectation = expectation(description: "Network was called")
interactor.downloadFile { _ in
XCTAssertEqual(URL(string: "https://a-url.com")!, session.lastURL)
expectation.fulfill()
}
wait(for: [expectation], timeout: 5)
}
}
The error I am receiving is Asynchronous wait failed: Exceeded timeout of 5 seconds, with unfulfilled expectations: "Network was called".
.
Please point me to the right direction.