我想测试NSURLSession,但收到错误“无法将简历发送到类NSURLSessionDataTask的抽象实例”。
示例代码在https://github.com/stevencurtis/abstract-instanceofclassNSURLSessionDataTask
中我的HTTP管理器工作正常:
class HTTPManager {
static let shared: HTTPManager = HTTPManager()
private let session: URLSessionProtocol
init(session: URLSessionProtocol = URLSession.shared) {
self.session = session
}
public func get(urlString: String, completionBlock: ((Data?) -> Void)?) {
let url = URL(string: urlString)
if let usableUrl = url {
let request = URLRequest(url: usableUrl)
let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
(completionBlock?(data))!
})
task.resume()
}
}
}
但是我尝试模拟它
class MockURLSession: URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
return URLSessionDataTask()
}
var searchedURL = URL(string: "asd")
}
然后创建测试:
func testGetRequest() {
let url = URL(string: "url")
let session = MockURLSession()
let sub = HTTPManager(session: session)
sub.get(urlString: "url", completionBlock: { [weak self] (data: Data?) -> Void in
print ("vc")
}
)
}
测试错误:不能将恢复发送到NSURLSessionDataTask类的抽象实例”,我想不出解决此错误的方法!
答案 0 :(得分:1)
HERE,有人重写了这篇文章,您可以在Playground中测试以下代码:
import UIKit
import XCTest
import PlaygroundSupport
import Foundation
// Protocol for MOCK/Real
protocol URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
protocol URLSessionDataTaskProtocol {
func resume()
}
//MARK: HttpClient Implementation
class HttpClient {
typealias completeClosure = ( _ data: Data?, _ error: Error?)->Void
private let session: URLSessionProtocol
init(session: URLSessionProtocol) {
self.session = session
}
func get( url: URL, callback: @escaping completeClosure ) {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.dataTask(with: request) { (data, response, error) in
callback(data, error)
}
task.resume()
}
}
//MARK: Conform the protocol
extension URLSession: URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping URLSessionProtocol.DataTaskResult) -> URLSessionDataTaskProtocol {
return dataTask(with: request, completionHandler: completionHandler) as URLSessionDataTask
}
}
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
//MARK: MOCK
class MockURLSession: URLSessionProtocol {
var nextDataTask = MockURLSessionDataTask()
var nextData: Data?
var nextError: Error?
private (set) var lastURL: URL?
func successHttpURLResponse(request: URLRequest) -> URLResponse {
return HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!
}
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
lastURL = request.url
completionHandler(nextData, successHttpURLResponse(request: request), nextError)
return nextDataTask
}
}
class MockURLSessionDataTask: URLSessionDataTaskProtocol {
private (set) var resumeWasCalled = false
func resume() {
resumeWasCalled = true
}
}
//MARK: Test
class HttpClientTests: XCTestCase {
var httpClient: HttpClient!
let session = MockURLSession()
override func setUp() {
super.setUp()
httpClient = HttpClient(session: session)
}
override func tearDown() {
super.tearDown()
}
func test_get_request_with_URL() {
guard let url = URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json") else {
fatalError("URL can't be empty")
}
httpClient.get(url: url) { (success, response) in
// Return data
}
XCTAssert(session.lastURL == url)
}
func test_get_resume_called() {
let dataTask = MockURLSessionDataTask()
session.nextDataTask = dataTask
guard let url = URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json") else {
fatalError("URL can't be empty")
}
httpClient.get(url: url) { (success, response) in
// Return data
}
XCTAssert(dataTask.resumeWasCalled)
}
func test_get_should_return_data() {
let expectedData = "{}".data(using: .utf8)
session.nextData = expectedData
var actualData: Data?
httpClient.get(url: URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json")!) { (data, error) in
actualData = data
}
XCTAssertNotNil(actualData)
}
}
HttpClientTests.defaultTestSuite.run()