测试 NSURLSession "resume cannot be sent to abstract instance of class NSURLSessionDataTask"
Testing NSURLSession "resume cannot be sent to abstract instance of class NSURLSessionDataTask"
我想测试 NSURLSession 但我收到错误 "resume cannot be sent to abstract instance of class 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")
}
)
}
测试错误:resume cannot be sent to abstract instance of class NSURLSessionDataTask”,我想不出解决这个错误的方法!
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()
我想测试 NSURLSession 但我收到错误 "resume cannot be sent to abstract instance of class 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")
}
)
}
测试错误:resume cannot be sent to abstract instance of class NSURLSessionDataTask”,我想不出解决这个错误的方法!
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()