-
Notifications
You must be signed in to change notification settings - Fork 0
모모의 URLSession Testable하게 만들기
DOHYUN CHUNG edited this page Sep 2, 2022
·
3 revisions
Mocking을 하는 방법은 2가지가 있다. protocol을 만들어서 채택시키고, 1. 그 protocol을 채택한 mocking 객체를 만들기 2. 상속한 다른 객체를 만들어서 init을 override 하기이다. 하지만 URLSession의 init은 deprecated 되어 있고, 다른 이니셜라이저가 다 public으로 되어있고 open으로 되어 있지 않다. 우리는 1번 방법으로 URLSession을 mocking 해서 Testable 하게 만들 수 있다.
URLSessionProtocol을 만들고, 실제의 URLSessionTask를 만드는 대신 URLSessionTaskProtocol을 만든다. URLSessionTaskProtocol을 사용해서 resume()
을 선언한다.
protocol URLSessionProtocol: AnyObject {
func makeDataTask(with url: URL, completionHandler: @escaping(Data?, URLResponse?, Error?) -> Void) -> URLSessionTaskProtocol
func makeDataTask(with request: URLRequest, completionHandler: @escaping(Data?, URLResponse?, Error?) -> Void) -> URLSessionTaskProtocol
}
protocol URLSessionTaskProtocol: AnyObject {
func resume()
}
URLSession이 URLSessionProtocol을 채택하도록 하고, URLSessionTask가 URLSessionTaskProtocol을 채택하도록 한다.
extension URLSessionTask: URLSessionTaskProtocol { }
extension URLSession: URLSessionProtocol {
/// makeDataTask를 활용해서 dataTask를 빼낸다. dataTask는 URLSessionDataTask를 return하는데 이는 URLSessionTaskProtocol을 채택하고 있다. 이렇게 Return을 URLSessionTaskProtocol을 하면서 URLSessionTaskProtocol을 채택한 어떠한 객체를 빼도 되기 때문에 mock을 하기에 유용하다.
/// - Parameters:
/// - url: URL
/// - completionHandler: (Data?, URLResponse?, Error?) -> Void 로 caller에서 처리할 때, Data로 뭐할것인지, Error로 뭐할것인지, URLResponse로 뭐할 것인지 적을 수 있다.
/// - Returns: URLSessionTaskProtocol
func makeDataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionTaskProtocol {
return dataTask(with: url, completionHandler: completionHandler)
}
/// makeDataTask를 활용해서 dataTask를 빼낸다. dataTask는 URLSessionDataTask를 return하는데 이는 URLSessionTaskProtocol을 채택하고 있다. 이렇게 Return을 URLSessionTaskProtocol을 하면서 URLSessionTaskProtocol을 채택한 어떠한 객체를 빼도 되기 때문에 mock을 하기에 유용하다.
/// - Parameters:
/// - request: URLRequest를 만들어서 param으로 던지기
/// - completionHandler: (Data?, URLResponse?, Error?) -> Void 로 caller에서 처리할 때, Data로 뭐할것인지, Error로 뭐할것인지, URLResponse로 뭐할 것인지 적을 수 있다.
/// - Returns: URLSessionTaskProtocol
func makeDataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionTaskProtocol {
return dataTask(with: request, completionHandler: completionHandler)
}
}