ResponseTests.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. //
  2. // ResponseTests.swift
  3. //
  4. // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. import Alamofire
  25. import Foundation
  26. import XCTest
  27. class ResponseTestCase: BaseTestCase {
  28. func testThatResponseReturnsSuccessResultWithValidData() {
  29. // Given
  30. let urlString = "https://httpbin.org/get"
  31. let expectation = self.expectation(description: "request should succeed")
  32. var response: DataResponse<Data?>?
  33. // When
  34. AF.request(urlString, parameters: ["foo": "bar"]).response { resp in
  35. response = resp
  36. expectation.fulfill()
  37. }
  38. waitForExpectations(timeout: timeout, handler: nil)
  39. // Then
  40. XCTAssertNotNil(response?.request)
  41. XCTAssertNotNil(response?.response)
  42. XCTAssertNotNil(response?.data)
  43. XCTAssertNil(response?.error)
  44. XCTAssertNotNil(response?.metrics)
  45. }
  46. func testThatResponseReturnsFailureResultWithOptionalDataAndError() {
  47. // Given
  48. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  49. let expectation = self.expectation(description: "request should fail with 404")
  50. var response: DataResponse<Data?>?
  51. // When
  52. AF.request(urlString, parameters: ["foo": "bar"]).response { resp in
  53. response = resp
  54. expectation.fulfill()
  55. }
  56. waitForExpectations(timeout: timeout, handler: nil)
  57. // Then
  58. XCTAssertNotNil(response?.request)
  59. XCTAssertNil(response?.response)
  60. XCTAssertNil(response?.data)
  61. XCTAssertNotNil(response?.error)
  62. XCTAssertNotNil(response?.metrics)
  63. }
  64. }
  65. // MARK: -
  66. class ResponseDataTestCase: BaseTestCase {
  67. func testThatResponseDataReturnsSuccessResultWithValidData() {
  68. // Given
  69. let urlString = "https://httpbin.org/get"
  70. let expectation = self.expectation(description: "request should succeed")
  71. var response: DataResponse<Data>?
  72. // When
  73. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  74. response = resp
  75. expectation.fulfill()
  76. }
  77. waitForExpectations(timeout: timeout, handler: nil)
  78. // Then
  79. XCTAssertNotNil(response?.request)
  80. XCTAssertNotNil(response?.response)
  81. XCTAssertNotNil(response?.data)
  82. XCTAssertNotNil(response?.data)
  83. XCTAssertEqual(response?.result.isSuccess, true)
  84. XCTAssertNotNil(response?.metrics)
  85. }
  86. func testThatResponseDataReturnsFailureResultWithOptionalDataAndError() {
  87. // Given
  88. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  89. let expectation = self.expectation(description: "request should fail with 404")
  90. var response: DataResponse<Data>?
  91. // When
  92. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  93. response = resp
  94. expectation.fulfill()
  95. }
  96. waitForExpectations(timeout: timeout, handler: nil)
  97. // Then
  98. XCTAssertNotNil(response?.request)
  99. XCTAssertNil(response?.response)
  100. XCTAssertNil(response?.data)
  101. XCTAssertEqual(response?.result.isFailure, true)
  102. XCTAssertNotNil(response?.metrics)
  103. }
  104. }
  105. // MARK: -
  106. class ResponseStringTestCase: BaseTestCase {
  107. func testThatResponseStringReturnsSuccessResultWithValidString() {
  108. // Given
  109. let urlString = "https://httpbin.org/get"
  110. let expectation = self.expectation(description: "request should succeed")
  111. var response: DataResponse<String>?
  112. // When
  113. AF.request(urlString, parameters: ["foo": "bar"]).responseString { resp in
  114. response = resp
  115. expectation.fulfill()
  116. }
  117. waitForExpectations(timeout: timeout, handler: nil)
  118. // Then
  119. XCTAssertNotNil(response?.request)
  120. XCTAssertNotNil(response?.response)
  121. XCTAssertNotNil(response?.data)
  122. XCTAssertNotNil(response?.data)
  123. XCTAssertEqual(response?.result.isSuccess, true)
  124. XCTAssertNotNil(response?.metrics)
  125. }
  126. func testThatResponseStringReturnsFailureResultWithOptionalDataAndError() {
  127. // Given
  128. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  129. let expectation = self.expectation(description: "request should fail with 404")
  130. var response: DataResponse<String>?
  131. // When
  132. AF.request(urlString, parameters: ["foo": "bar"]).responseString { resp in
  133. response = resp
  134. expectation.fulfill()
  135. }
  136. waitForExpectations(timeout: timeout, handler: nil)
  137. // Then
  138. XCTAssertNotNil(response?.request)
  139. XCTAssertNil(response?.response)
  140. XCTAssertNil(response?.data)
  141. XCTAssertEqual(response?.result.isFailure, true)
  142. XCTAssertNotNil(response?.metrics)
  143. }
  144. }
  145. // MARK: -
  146. class ResponseJSONTestCase: BaseTestCase {
  147. func testThatResponseJSONReturnsSuccessResultWithValidJSON() {
  148. // Given
  149. let urlString = "https://httpbin.org/get"
  150. let expectation = self.expectation(description: "request should succeed")
  151. var response: DataResponse<Any>?
  152. // When
  153. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  154. response = resp
  155. expectation.fulfill()
  156. }
  157. waitForExpectations(timeout: timeout, handler: nil)
  158. // Then
  159. XCTAssertNotNil(response?.request)
  160. XCTAssertNotNil(response?.response)
  161. XCTAssertNotNil(response?.data)
  162. XCTAssertNotNil(response?.data)
  163. XCTAssertEqual(response?.result.isSuccess, true)
  164. XCTAssertNotNil(response?.metrics)
  165. }
  166. func testThatResponseStringReturnsFailureResultWithOptionalDataAndError() {
  167. // Given
  168. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  169. let expectation = self.expectation(description: "request should fail")
  170. var response: DataResponse<Any>?
  171. // When
  172. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  173. response = resp
  174. expectation.fulfill()
  175. }
  176. waitForExpectations(timeout: timeout, handler: nil)
  177. // Then
  178. XCTAssertNotNil(response?.request)
  179. XCTAssertNil(response?.response)
  180. XCTAssertNil(response?.data)
  181. XCTAssertEqual(response?.result.isFailure, true)
  182. XCTAssertNotNil(response?.metrics)
  183. }
  184. func testThatResponseJSONReturnsSuccessResultForGETRequest() {
  185. // Given
  186. let urlString = "https://httpbin.org/get"
  187. let expectation = self.expectation(description: "request should succeed")
  188. var response: DataResponse<Any>?
  189. // When
  190. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  191. response = resp
  192. expectation.fulfill()
  193. }
  194. waitForExpectations(timeout: timeout, handler: nil)
  195. // Then
  196. XCTAssertNotNil(response?.request)
  197. XCTAssertNotNil(response?.response)
  198. XCTAssertNotNil(response?.data)
  199. XCTAssertNotNil(response?.data)
  200. XCTAssertEqual(response?.result.isSuccess, true)
  201. XCTAssertNotNil(response?.metrics)
  202. if
  203. let responseDictionary = response?.result.value as? [String: Any],
  204. let args = responseDictionary["args"] as? [String: String]
  205. {
  206. XCTAssertEqual(args, ["foo": "bar"], "args should match parameters")
  207. } else {
  208. XCTFail("args should not be nil")
  209. }
  210. }
  211. func testThatResponseJSONReturnsSuccessResultForPOSTRequest() {
  212. // Given
  213. let urlString = "https://httpbin.org/post"
  214. let expectation = self.expectation(description: "request should succeed")
  215. var response: DataResponse<Any>?
  216. // When
  217. AF.request(urlString, method: .post, parameters: ["foo": "bar"]).responseJSON { resp in
  218. response = resp
  219. expectation.fulfill()
  220. }
  221. waitForExpectations(timeout: timeout, handler: nil)
  222. // Then
  223. XCTAssertNotNil(response?.request)
  224. XCTAssertNotNil(response?.response)
  225. XCTAssertNotNil(response?.data)
  226. XCTAssertNotNil(response?.data)
  227. XCTAssertEqual(response?.result.isSuccess, true)
  228. XCTAssertNotNil(response?.metrics)
  229. if
  230. let responseDictionary = response?.result.value as? [String: Any],
  231. let form = responseDictionary["form"] as? [String: String]
  232. {
  233. XCTAssertEqual(form, ["foo": "bar"], "form should match parameters")
  234. } else {
  235. XCTFail("form should not be nil")
  236. }
  237. }
  238. }
  239. class ResponseJSONDecodableTestCase: BaseTestCase {
  240. func testThatResponseJSONReturnsSuccessResultWithValidJSON() {
  241. // Given
  242. let urlString = "https://httpbin.org/get"
  243. let expectation = self.expectation(description: "request should succeed")
  244. var response: DataResponse<HTTPBinResponse>?
  245. // When
  246. AF.request(urlString, parameters: [:]).responseDecodable { (resp: DataResponse<HTTPBinResponse>) in
  247. response = resp
  248. expectation.fulfill()
  249. }
  250. waitForExpectations(timeout: timeout, handler: nil)
  251. // Then
  252. XCTAssertNotNil(response?.request)
  253. XCTAssertNotNil(response?.response)
  254. XCTAssertNotNil(response?.data)
  255. XCTAssertEqual(response?.result.isSuccess, true)
  256. XCTAssertEqual(response?.result.value?.url, "https://httpbin.org/get")
  257. XCTAssertNotNil(response?.metrics)
  258. }
  259. func testThatResponseStringReturnsFailureResultWithOptionalDataAndError() {
  260. // Given
  261. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  262. let expectation = self.expectation(description: "request should fail")
  263. var response: DataResponse<HTTPBinResponse>?
  264. // When
  265. AF.request(urlString, parameters: [:]).responseDecodable { (resp: DataResponse<HTTPBinResponse>) in
  266. response = resp
  267. expectation.fulfill()
  268. }
  269. waitForExpectations(timeout: timeout, handler: nil)
  270. // Then
  271. XCTAssertNotNil(response?.request)
  272. XCTAssertNil(response?.response)
  273. XCTAssertNil(response?.data)
  274. XCTAssertEqual(response?.result.isFailure, true)
  275. XCTAssertNotNil(response?.metrics)
  276. }
  277. }
  278. // MARK: -
  279. class ResponseMapTestCase: BaseTestCase {
  280. func testThatMapTransformsSuccessValue() {
  281. // Given
  282. let urlString = "https://httpbin.org/get"
  283. let expectation = self.expectation(description: "request should succeed")
  284. var response: DataResponse<String>?
  285. // When
  286. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  287. response = resp.map { json in
  288. // json["args"]["foo"] is "bar": use this invariant to test the map function
  289. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  290. }
  291. expectation.fulfill()
  292. }
  293. waitForExpectations(timeout: timeout, handler: nil)
  294. // Then
  295. XCTAssertNotNil(response?.request)
  296. XCTAssertNotNil(response?.response)
  297. XCTAssertNotNil(response?.data)
  298. XCTAssertEqual(response?.result.isSuccess, true)
  299. XCTAssertEqual(response?.result.value, "bar")
  300. XCTAssertNotNil(response?.metrics)
  301. }
  302. func testThatMapPreservesFailureError() {
  303. // Given
  304. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  305. let expectation = self.expectation(description: "request should fail with 404")
  306. var response: DataResponse<String>?
  307. // When
  308. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  309. response = resp.map { _ in "ignored" }
  310. expectation.fulfill()
  311. }
  312. waitForExpectations(timeout: timeout, handler: nil)
  313. // Then
  314. XCTAssertNotNil(response?.request)
  315. XCTAssertNil(response?.response)
  316. XCTAssertNil(response?.data)
  317. XCTAssertEqual(response?.result.isFailure, true)
  318. XCTAssertNotNil(response?.metrics)
  319. }
  320. }
  321. // MARK: -
  322. class ResponseFlatMapTestCase: BaseTestCase {
  323. func testThatFlatMapTransformsSuccessValue() {
  324. // Given
  325. let urlString = "https://httpbin.org/get"
  326. let expectation = self.expectation(description: "request should succeed")
  327. var response: DataResponse<String>?
  328. // When
  329. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  330. response = resp.flatMap { json in
  331. // json["args"]["foo"] is "bar": use this invariant to test the flatMap function
  332. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  333. }
  334. expectation.fulfill()
  335. }
  336. waitForExpectations(timeout: timeout, handler: nil)
  337. // Then
  338. XCTAssertNotNil(response?.request)
  339. XCTAssertNotNil(response?.response)
  340. XCTAssertNotNil(response?.data)
  341. XCTAssertEqual(response?.result.isSuccess, true)
  342. XCTAssertEqual(response?.result.value, "bar")
  343. XCTAssertNotNil(response?.metrics)
  344. }
  345. func testThatFlatMapCatchesTransformationError() {
  346. // Given
  347. struct TransformError: Error {}
  348. let urlString = "https://httpbin.org/get"
  349. let expectation = self.expectation(description: "request should succeed")
  350. var response: DataResponse<String>?
  351. // When
  352. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  353. response = resp.flatMap { json in
  354. throw TransformError()
  355. }
  356. expectation.fulfill()
  357. }
  358. waitForExpectations(timeout: timeout, handler: nil)
  359. // Then
  360. XCTAssertNotNil(response?.request)
  361. XCTAssertNotNil(response?.response)
  362. XCTAssertNotNil(response?.data)
  363. XCTAssertEqual(response?.result.isFailure, true)
  364. if let error = response?.result.error {
  365. XCTAssertTrue(error is TransformError)
  366. } else {
  367. XCTFail("flatMap should catch the transformation error")
  368. }
  369. XCTAssertNotNil(response?.metrics)
  370. }
  371. func testThatFlatMapPreservesFailureError() {
  372. // Given
  373. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  374. let expectation = self.expectation(description: "request should fail with 404")
  375. var response: DataResponse<String>?
  376. // When
  377. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  378. response = resp.flatMap { _ in "ignored" }
  379. expectation.fulfill()
  380. }
  381. waitForExpectations(timeout: timeout, handler: nil)
  382. // Then
  383. XCTAssertNotNil(response?.request)
  384. XCTAssertNil(response?.response)
  385. XCTAssertNil(response?.data)
  386. XCTAssertEqual(response?.result.isFailure, true)
  387. XCTAssertNotNil(response?.metrics)
  388. }
  389. }
  390. // MARK: -
  391. enum TestError: Error {
  392. case error(error: Error)
  393. }
  394. enum TransformationError: Error {
  395. case error
  396. func alwaysFails() throws -> TestError {
  397. throw TransformationError.error
  398. }
  399. }
  400. class ResponseMapErrorTestCase: BaseTestCase {
  401. func testThatMapErrorTransformsFailureValue() {
  402. // Given
  403. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  404. let expectation = self.expectation(description: "request should not succeed")
  405. var response: DataResponse<Any>?
  406. // When
  407. AF.request(urlString).responseJSON { resp in
  408. response = resp.mapError { error in
  409. return TestError.error(error: error)
  410. }
  411. expectation.fulfill()
  412. }
  413. waitForExpectations(timeout: timeout, handler: nil)
  414. // Then
  415. XCTAssertNotNil(response?.request)
  416. XCTAssertNil(response?.response)
  417. XCTAssertNil(response?.data)
  418. XCTAssertEqual(response?.result.isFailure, true)
  419. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  420. XCTAssertNotNil(response?.metrics)
  421. }
  422. func testThatMapErrorPreservesSuccessValue() {
  423. // Given
  424. let urlString = "https://httpbin.org/get"
  425. let expectation = self.expectation(description: "request should succeed")
  426. var response: DataResponse<Data>?
  427. // When
  428. AF.request(urlString).responseData { resp in
  429. response = resp.mapError { TestError.error(error: $0) }
  430. expectation.fulfill()
  431. }
  432. waitForExpectations(timeout: timeout, handler: nil)
  433. // Then
  434. XCTAssertNotNil(response?.request)
  435. XCTAssertNotNil(response?.response)
  436. XCTAssertNotNil(response?.data)
  437. XCTAssertEqual(response?.result.isSuccess, true)
  438. XCTAssertNotNil(response?.metrics)
  439. }
  440. }
  441. // MARK: -
  442. class ResponseFlatMapErrorTestCase: BaseTestCase {
  443. func testThatFlatMapErrorPreservesSuccessValue() {
  444. // Given
  445. let urlString = "https://httpbin.org/get"
  446. let expectation = self.expectation(description: "request should succeed")
  447. var response: DataResponse<Data>?
  448. // When
  449. AF.request(urlString).responseData { resp in
  450. response = resp.flatMapError { TestError.error(error: $0) }
  451. expectation.fulfill()
  452. }
  453. waitForExpectations(timeout: timeout, handler: nil)
  454. // Then
  455. XCTAssertNotNil(response?.request)
  456. XCTAssertNotNil(response?.response)
  457. XCTAssertNotNil(response?.data)
  458. XCTAssertEqual(response?.result.isSuccess, true)
  459. XCTAssertNotNil(response?.metrics)
  460. }
  461. func testThatFlatMapErrorCatchesTransformationError() {
  462. // Given
  463. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  464. let expectation = self.expectation(description: "request should fail")
  465. var response: DataResponse<Data>?
  466. // When
  467. AF.request(urlString).responseData { resp in
  468. response = resp.flatMapError { _ in try TransformationError.error.alwaysFails() }
  469. expectation.fulfill()
  470. }
  471. waitForExpectations(timeout: timeout, handler: nil)
  472. // Then
  473. XCTAssertNotNil(response?.request)
  474. XCTAssertNil(response?.response)
  475. XCTAssertNil(response?.data)
  476. XCTAssertEqual(response?.result.isFailure, true)
  477. if let error = response?.result.error {
  478. XCTAssertTrue(error is TransformationError)
  479. } else {
  480. XCTFail("flatMapError should catch the transformation error")
  481. }
  482. XCTAssertNotNil(response?.metrics)
  483. }
  484. func testThatFlatMapErrorTransformsError() {
  485. // Given
  486. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  487. let expectation = self.expectation(description: "request should fail")
  488. var response: DataResponse<Data>?
  489. // When
  490. AF.request(urlString).responseData { resp in
  491. response = resp.flatMapError { TestError.error(error: $0) }
  492. expectation.fulfill()
  493. }
  494. waitForExpectations(timeout: timeout, handler: nil)
  495. // Then
  496. XCTAssertNotNil(response?.request)
  497. XCTAssertNil(response?.response)
  498. XCTAssertNil(response?.data)
  499. XCTAssertEqual(response?.result.isFailure, true)
  500. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  501. XCTAssertNotNil(response?.metrics)
  502. }
  503. }