OHHTTPStubs
OHHTTPStubs
是一个设计用于非常容易地对网络请求进行模拟的库。它可以帮助您
- 使用来自文件的真实网络数据(模拟网络数据)和模拟慢速网络来测试您的应用程序,检查应用程序在不良网络条件下的行为
- 编写使用您的固定数据的模拟网络数据来编写的单元测试。
它与 NSURLConnection
、NSURLSession
、AFNetworking
、Alamofire
或任何使用 Cocoa 的 URL 加载系统的网络框架一起工作。
文档和用法示例
OHHTTPStubs
的头部使用与 Appledoc 类似 / Headerdoc 类似的注释进行了详细文档说明。您还可以 在此处阅读 在线文档。
基本示例
在 Objective-C 中
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return [request.URL.host isEqualToString:@"mywebservice.com"];
} withStubResponse:^HTTPStubsResponse*(NSURLRequest *request) {
// Stub it with our "wsresponse.json" stub file (which is in same bundle as self)
NSString* fixture = OHPathForFile(@"wsresponse.json", self.class);
return [HTTPStubsResponse responseWithFileAtPath:fixture
statusCode:200 headers:@{@"Content-Type":@"application/json"}];
}];
在 Swift 中
此示例使用在 OHHTTPStubs/Swift
subspec 或 OHHTTPStubs
包提供的 OHHTTPStubsSwift.swift
中找到的 Swift 辅助工具。
stub(condition: isHost("mywebservice.com")) { _ in
// Stub it with our "wsresponse.json" stub file (which is in same bundle as self)
let stubPath = OHPathForFile("wsresponse.json", type(of: self))
return fixture(filePath: stubPath!, headers: ["Content-Type":"application/json"])
}
注意:如果您正在使用 OHHTTPStubs
的 Swiftier API(《OHHTTPStubsSwift.swift 和 Swift
子规范或 OHTTPStubsSwift
包)),您也可以像这样组合匹配函数:stub(isScheme("http") && isHost("myhost")) { … }
更多示例及帮助主题
- 更多示例,请参阅专门的 "使用示例" 维基页面。
- 维基还包含一些可以帮助您开始使用 (并如有需要则进行故障排除)
OHHTTPStubs
的文章。
记录请求以稍后回放
您可以将您想使用的存根内容手动写入,也可以使用 SWHttpTrafficRecorder 等工具将网络请求记录到文件中。这样您就可以稍后使用这些文件作为存根响应。
此工具可以记录 OHHTTPStubs
支持的三个格式(HTTPMessage
格式、简单的响应正文/内容文件和 Mocktail
格式)。
(还有其他执行类似任务的方法,包括使用 curl -is <url> >foo.response
生成与 HTTPMessage
格式兼容的文件,或使用类似 SWHttpTrafficRecorder
的其他网络记录库)。
兼容性
OHHTTPStubs
与 iOS5+、OS X 10.7+、tvOS 兼容。OHHTTPStubs
还与NSURLSession
以及任何包装它们的网络库一起使用。OHHTTPStubs
完全兼容 Swift 3.x、4.x 和 Swift 5.x。
nullability 注释 已添加到 ObjC API 中,以便在使用 OHHTTPStubsSwift.swift
提供的专用 Swift API 包装器时获得更干净的 API,即使您没有使用它。
升级到版本 9.0+
- 所有类都放弃了
OH
前缀(从OHHHTTPStubs
到HTTPStubs
,从OHHTTPStubsResponse
到HTTPStubsResponse
等)。 OHPathHelpers
类已重命名为HTTPStubsPathHelpers
。- 方法和模块名称都没有更改。
在您的项目中安装
CocoaPods
使用 CocoaPods 是推荐的方式。
- 如果您仅打算从 Objective-C 使用
OHHTTPStubs
,请在您的Podfile
中添加pod 'OHHTTPStubs'
。 - 如果您打算从 Swift 使用
OHHTTPStubs
,则改在您的Podfile
中添加pod 'OHHTTPStubs/Swift'
。
pod 'OHHTTPStubs/Swift' # includes the Default subspec, with support for NSURLSession & JSON, and the Swiftier API wrappers
所有可用子规格
为了在使用 Cocoapods 时不增加不必要的依赖,OHHTTPStubs
已经被拆分成子规格。
- 默认子规格包括
NSURLSession
、JSON
和OHPathHelpers
。 - Swift 子规格添加了更简洁的 API 到默认子规格中。
HTTPMessage
和Mocktail
是可选子规格:如果您需要,请明确列出。OHPathHelpers
不依赖于Core
,并且可以独立于OHHTTPStubs
一起使用。
所有子规格及其依赖项列表
以下是您在 Podfile
中使用时包含的子规格的列表。
子规格 | 核心 | NSURLSession | JSON | Swift | OHPathHelpers | HTTPMessage | Mocktail |
---|---|---|---|---|---|---|---|
pod 'OHHTTPStubs' |
|||||||
pod 'OHHTTPStubs/Default' |
|||||||
pod 'OHHTTPStubs/Swift' |
|||||||
pod 'OHHTTPStubs/Core' |
|||||||
pod 'OHHTTPStubs/NSURLSession' |
|||||||
pod 'OHHTTPStubs/JSON' |
|||||||
pod 'OHHTTPStubs/OHPathHelpers' |
|||||||
pod 'OHHTTPStubs/HTTPMessage' |
|||||||
pod 'OHHTTPStubs/Mocktail' |
Swift 包管理器
与 Swift 包管理器兼容的 OHHTTPStubs
提供了 2 个用于消费的目标:OHHTTPStubs
和 OHHTTPStubsSwift
。
OHHTTPStubs
等同于OHHTTPStubs
子规格。OHHTTPStubsSwift
等同于OHHTTPStubs/Swift
子规格。
注意:目前我们对 HTTPMessage 或 Mocktail 子规格在 Swift 包管理器中没有支持。如果您对此感兴趣,请提交一个问题来解释您的需求。
Carthage
OHHTTPStubs
也与Carthage兼容。只需将其添加到你的Cartfile
中即可。
注意:使用Carthage构建的OHHTTPStubs.framework
将包含OHHTTPStubs
的所有功能(换言之,包含pod的所有subsbcpec),包括NSURLSession
和JSON
支持,OHPathHelpers
,HTTPMessage
和Mocktail
支持,以及Swifter API。
为你项目选择正确的Swift版本
OHHTTPStubs
支持Swift 3.0(Xcode 8+),Swift 3.1(Xcode 8.3+),Swift 3.2(Xcode 9.0+),Swift 4.0(Xcode 9.0+),Swift 4.1(Xcode 9.3+),Swift 4.2(Xcode 10+),Swift 5.0(Xcode 10.2),以及Swift 5.1(Xcode 11),但我们在CI中仅测试了Swift 4.x(使用Xcode 9.1和10.1)和Swift 5.x(使用Xcode 10.2和11)。
以下是一些关于如何集成OHHTTPStubs
到你的项目中所需的正确设置的详细信息。
CocoaPods:无需操作
如果你使用CocoaPods版本1.1.0.beta.1
或更高版本,那么CocoaPods将自动使用与你的项目相同的正确Swift版本来编译OHHTTPStubs
。你无需做任何事情!
Carthage:选择正确的版本
“master”预设了SWIFT_VERSION=5.0
。
这意味着“master”中框架的构建将使用
- Xcode 11的Swift 5.1
- Xcode 10.2的Swift 5.0
- Xcode 10.1的Swift 4.2
- Xcode 9.1的Swift 4.0
如果你想要Carthage使用Swift 3.x来构建框架,你可以
- 使用较老的Xcode版本
- 或使用
OHHTTPStubs
的先前的版本(6.2.0)——其master
分支使用3.0
- 或创建分支机构以仅更改构建设置中的
SWIFT_VERSION
为3.0
- 或通过
XCODE_XCCONFIG_FILE=<config file declaring SWIFT_VERSION> carthage build
向carthage传递一个SWIFT_VERSION
来构建框架
特殊注意事项
在单元测试中使用 OHHTTPStubs
OHHTTPStubs
是编写通常执行网络请求的单元测试的理想选择。但如果你在单元测试中使用它,别忘了
- 在每次测试后删除你安装的任何存根 - 以防止这些存根在执行下一个测试用例时仍然安装 - 通过在
tearDown
方法中调用[HTTPStubs removeAllStubs]
来实现。有关更多信息,请参阅此维基页面 - 务必等待请求收到响应后再进行断言并完成测试用例(类似于任何异步测试)。有关更多信息,请参阅此维基页面
自动加载
OHHTTPStubs
会自动加载和安装(在库加载到内存中的时候),无论是用于
- 使用
NSURLConnection
或[NSURLSession sharedSession]
发起的请求 - 感谢以下代码的支持 - 使用通过
[NSURLSession sessionWithConfiguration:…]
创建的NSURLSession
,并使用[NSURLSessionConfiguration defaultSessionConfiguration]
或[NSURLSessionConfiguration ephemeralSessionConfiguration]
配置 - 感谢方法交换,这部分代码位于这里。
如果您需要全局或按 NSURLSession
禁用(和重新启用)OHHTTPStubs
,可以使用 [HTTPStubs setEnabled:]
/ [HTTPStubs setEnabled:forSessionConfiguration:]
。
已知限制
OHHTTPStubs
不适用于后台会话(使用[NSURLSessionConfiguration backgroundSessionConfiguration]
创建的会话),因为后台会话不允许使用自定义的NSURLProtocols
,并且由 iOS 操作系统本身处理。OHHTTPStubs
不模拟数据上传。由于NSURLProtocolClient
@protocol
无法提供一种方法使委托知道数据已发送(只能指示已加载部分),因此HTTPBody
或HTTPBodyStream
中的任何数据、或在NSURLRequest
中提供的数据,甚至是提供给-[NSURLSession uploadTaskWithRequest:fromData:];
的数据都将被忽略,更重要的是,当使用OHHTTPStubs
模拟请求时,将永远不会调用-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
委托方法。OHTTPStubs
存在一个已知的重定向问题,我们认为这是苹果的一个bug。这个问题已在这里和这里进行了讨论。这个bug的实际结果是,延迟为零秒的重定向可能会随机得到一个空响应。
据我所知,我们无法解决这三个限制中的任何一个。如果您知道一种解决方案,使这成为可能,请告诉我。
提交到App Store
OHHTTPStubs
可用于提交到App Store的应用。它不会使用任何私有API,没有任何阻止你发布它的因素。
但您通常只在前端开发阶段使用存根,希望在提交到App Store时删除存根。因此,请确保只在需要时包含OHHTTPStubs
(只在测试目标中、只在#if DEBUG
部分中,或通过使用按构建配置的pods)以避免在您提交到App Store并希望您的请求触及真实网络时忘记删除它!
许可证和致谢
本项目和库由Olivier Halligon创建(Twitter:@aligatr),并受MIT许可证的约束。
该项目受到了InfiniteLoop.dk上的这篇文章的启发。
我还要感谢
- Sébastien Duperron(GitHub:@Liquidsoul)帮助我维护此库,对会话和PR进行分类并作出回应
- Kevin Harwood(GitHub:@kcharwood)将代码迁移到
NSInputStream
- Jinlian Wang(GitHub:@JinlianWang)增加Mocktail支持
- 以及为GitHub上的此项目做出贡献的每个人。