我正在寻找一种最有效的方法来对使用NSURLSession
从URL检索数据的类进行单元测试。我已经看到了实现NSURLConnectionDelegate
协议的类的较旧示例。从阅读NSURLSession
类参考文档,到使用相同的方法,我的类必须实现NSURLSessionDataDelegate
协议。我相信这也需要实现NSURLSessionTaskDelegate
和NSURLSessionDelegate
协议,这些协议一起包含许多我不需要的方法。
是否有更简单的方法来实现相同的目标?
感谢。
答案 0 :(得分:0)
我更喜欢使用面向协议的编程和协议扩展来测试NSURLSession
。以下是我的博文"Testing NSURLSession with Swift, Part 1: Mocking Classes You Don't Own"的摘要。
首先,为NSURLSessionDataTask
创建一个协议,以便用测试中的模拟代替它。
typealias DataTaskResult = (NSData?, NSURLResponse?, NSError?) -> Void
protocol URLSessionProtocol {
func dataTaskWithURL(url: NSURL, completionHandler: DataTaskResult)
-> NSURLSessionDataTask
}
然后扩展框架类,以便编译器知道协议和类可以互换使用。
extension NSURLSession: URLSessionProtocol { }
现在您可以创建一个模拟会话来捕获传入的参数。
class MockURLSession: URLSessionProtocol {
private (set) var lastURL: NSURL?
func dataTaskWithURL(url: NSURL, completionHandler: DataTaskResult)
-> NSURLSessionDataTask
{
lastURL = url
return NSURLSessionDataTask()
}
}
最后,测试您的HTTPClient
是否向会话发送了正确的网址。
class HTTPClientTests: XCTestCase {
var subject: HTTPClient!
let session = MockURLSession()
override func setUp() {
super.setUp()
subject = HTTPClient(session: session)
}
func test_GET_RequestsTheURL() {
let url = NSURL(string: "http://masilotti.com")!
subject.get(url) { (_, _) -> Void in }
XCTAssert(session.lastURL === url)
}
}
确保HTTPClient
通过依赖注入公开URLSessionProtocol
属性。在这里,您可以使用默认参数在未注入任何内容时获取共享会话。
class HTTPClient {
private let session: URLSessionProtocol
init(session: URLSessionProtocol = NSURLSession.sharedSession()) {
self.session = session
}
func get(url: NSURL, completion: HTTPResult) {
session.dataTaskWithURL(url) { (_, _, _) -> Void in }
}
}
这可以很容易地扩展到测试更多输入,其他方法甚至输出。再次,请查看my blog post以获取更详细的说明和示例。