ResponseTests.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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?, AFError>?
  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?, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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, AFError>?
  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 testThatResponseDecodableReturnsSuccessResultWithValidJSON() {
  241. // Given
  242. let urlString = "https://httpbin.org/get"
  243. let expectation = self.expectation(description: "request should succeed")
  244. var response: DataResponse<HTTPBinResponse, AFError>?
  245. // When
  246. AF.request(urlString, parameters: [:]).responseDecodable(of: HTTPBinResponse.self) { resp 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 testThatResponseDecodableWithPassedTypeReturnsSuccessResultWithValidJSON() {
  260. // Given
  261. let urlString = "https://httpbin.org/get"
  262. let expectation = self.expectation(description: "request should succeed")
  263. var response: DataResponse<HTTPBinResponse, AFError>?
  264. // When
  265. AF.request(urlString, parameters: [:]).responseDecodable(of: HTTPBinResponse.self) {
  266. response = $0
  267. expectation.fulfill()
  268. }
  269. waitForExpectations(timeout: timeout, handler: nil)
  270. // Then
  271. XCTAssertNotNil(response?.request)
  272. XCTAssertNotNil(response?.response)
  273. XCTAssertNotNil(response?.data)
  274. XCTAssertEqual(response?.result.isSuccess, true)
  275. XCTAssertEqual(response?.result.value?.url, "https://httpbin.org/get")
  276. XCTAssertNotNil(response?.metrics)
  277. }
  278. func testThatResponseStringReturnsFailureResultWithOptionalDataAndError() {
  279. // Given
  280. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  281. let expectation = self.expectation(description: "request should fail")
  282. var response: DataResponse<HTTPBinResponse, AFError>?
  283. // When
  284. AF.request(urlString, parameters: [:]).responseDecodable(of: HTTPBinResponse.self) { resp in
  285. response = resp
  286. expectation.fulfill()
  287. }
  288. waitForExpectations(timeout: timeout, handler: nil)
  289. // Then
  290. XCTAssertNotNil(response?.request)
  291. XCTAssertNil(response?.response)
  292. XCTAssertNil(response?.data)
  293. XCTAssertEqual(response?.result.isFailure, true)
  294. XCTAssertNotNil(response?.metrics)
  295. }
  296. }
  297. // MARK: -
  298. class ResponseMapTestCase: BaseTestCase {
  299. func testThatMapTransformsSuccessValue() {
  300. // Given
  301. let urlString = "https://httpbin.org/get"
  302. let expectation = self.expectation(description: "request should succeed")
  303. var response: DataResponse<String, AFError>?
  304. // When
  305. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  306. response = resp.map { json in
  307. // json["args"]["foo"] is "bar": use this invariant to test the map function
  308. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  309. }
  310. expectation.fulfill()
  311. }
  312. waitForExpectations(timeout: timeout, handler: nil)
  313. // Then
  314. XCTAssertNotNil(response?.request)
  315. XCTAssertNotNil(response?.response)
  316. XCTAssertNotNil(response?.data)
  317. XCTAssertEqual(response?.result.isSuccess, true)
  318. XCTAssertEqual(response?.result.value, "bar")
  319. XCTAssertNotNil(response?.metrics)
  320. }
  321. func testThatMapPreservesFailureError() {
  322. // Given
  323. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  324. let expectation = self.expectation(description: "request should fail with 404")
  325. var response: DataResponse<String, AFError>?
  326. // When
  327. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  328. response = resp.map { _ in "ignored" }
  329. expectation.fulfill()
  330. }
  331. waitForExpectations(timeout: timeout, handler: nil)
  332. // Then
  333. XCTAssertNotNil(response?.request)
  334. XCTAssertNil(response?.response)
  335. XCTAssertNil(response?.data)
  336. XCTAssertEqual(response?.result.isFailure, true)
  337. XCTAssertNotNil(response?.metrics)
  338. }
  339. }
  340. // MARK: -
  341. class ResponseTryMapTestCase: BaseTestCase {
  342. func testThatTryMapTransformsSuccessValue() {
  343. // Given
  344. let urlString = "https://httpbin.org/get"
  345. let expectation = self.expectation(description: "request should succeed")
  346. var response: DataResponse<String, Error>?
  347. // When
  348. AF.request(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  349. response = resp.tryMap { json in
  350. // json["args"]["foo"] is "bar": use this invariant to test the tryMap function
  351. return ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  352. }
  353. expectation.fulfill()
  354. }
  355. waitForExpectations(timeout: timeout, handler: nil)
  356. // Then
  357. XCTAssertNotNil(response?.request)
  358. XCTAssertNotNil(response?.response)
  359. XCTAssertNotNil(response?.data)
  360. XCTAssertEqual(response?.result.isSuccess, true)
  361. XCTAssertEqual(response?.result.value, "bar")
  362. XCTAssertNotNil(response?.metrics)
  363. }
  364. func testThatTryMapCatchesTransformationError() {
  365. // Given
  366. struct TransformError: Error {}
  367. let urlString = "https://httpbin.org/get"
  368. let expectation = self.expectation(description: "request should succeed")
  369. var response: DataResponse<String, Error>?
  370. // When
  371. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  372. response = resp.tryMap { json in
  373. throw TransformError()
  374. }
  375. expectation.fulfill()
  376. }
  377. waitForExpectations(timeout: timeout, handler: nil)
  378. // Then
  379. XCTAssertNotNil(response?.request)
  380. XCTAssertNotNil(response?.response)
  381. XCTAssertNotNil(response?.data)
  382. XCTAssertEqual(response?.result.isFailure, true)
  383. if let error = response?.result.error {
  384. XCTAssertTrue(error is TransformError)
  385. } else {
  386. XCTFail("tryMap should catch the transformation error")
  387. }
  388. XCTAssertNotNil(response?.metrics)
  389. }
  390. func testThatTryMapPreservesFailureError() {
  391. // Given
  392. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  393. let expectation = self.expectation(description: "request should fail with 404")
  394. var response: DataResponse<String, Error>?
  395. // When
  396. AF.request(urlString, parameters: ["foo": "bar"]).responseData { resp in
  397. response = resp.tryMap { _ in "ignored" }
  398. expectation.fulfill()
  399. }
  400. waitForExpectations(timeout: timeout, handler: nil)
  401. // Then
  402. XCTAssertNotNil(response?.request)
  403. XCTAssertNil(response?.response)
  404. XCTAssertNil(response?.data)
  405. XCTAssertEqual(response?.result.isFailure, true)
  406. XCTAssertNotNil(response?.metrics)
  407. }
  408. }
  409. // MARK: -
  410. enum TestError: Error {
  411. case error(error: Error)
  412. }
  413. enum TransformationError: Error {
  414. case error
  415. func alwaysFails() throws -> TestError {
  416. throw TransformationError.error
  417. }
  418. }
  419. class ResponseMapErrorTestCase: BaseTestCase {
  420. func testThatMapErrorTransformsFailureValue() {
  421. // Given
  422. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  423. let expectation = self.expectation(description: "request should not succeed")
  424. var response: DataResponse<Any, TestError>?
  425. // When
  426. AF.request(urlString).responseJSON { resp in
  427. response = resp.mapError { error in
  428. return TestError.error(error: error)
  429. }
  430. expectation.fulfill()
  431. }
  432. waitForExpectations(timeout: timeout, handler: nil)
  433. // Then
  434. XCTAssertNotNil(response?.request)
  435. XCTAssertNil(response?.response)
  436. XCTAssertNil(response?.data)
  437. XCTAssertEqual(response?.result.isFailure, true)
  438. guard let error = response?.error, case .error = error else { XCTFail(); return }
  439. XCTAssertNotNil(response?.metrics)
  440. }
  441. func testThatMapErrorPreservesSuccessValue() {
  442. // Given
  443. let urlString = "https://httpbin.org/get"
  444. let expectation = self.expectation(description: "request should succeed")
  445. var response: DataResponse<Data, TestError>?
  446. // When
  447. AF.request(urlString).responseData { resp in
  448. response = resp.mapError { TestError.error(error: $0) }
  449. expectation.fulfill()
  450. }
  451. waitForExpectations(timeout: timeout, handler: nil)
  452. // Then
  453. XCTAssertNotNil(response?.request)
  454. XCTAssertNotNil(response?.response)
  455. XCTAssertNotNil(response?.data)
  456. XCTAssertEqual(response?.result.isSuccess, true)
  457. XCTAssertNotNil(response?.metrics)
  458. }
  459. }
  460. // MARK: -
  461. class ResponseTryMapErrorTestCase: BaseTestCase {
  462. func testThatTryMapErrorPreservesSuccessValue() {
  463. // Given
  464. let urlString = "https://httpbin.org/get"
  465. let expectation = self.expectation(description: "request should succeed")
  466. var response: DataResponse<Data, Error>?
  467. // When
  468. AF.request(urlString).responseData { resp in
  469. response = resp.tryMapError { TestError.error(error: $0) }
  470. expectation.fulfill()
  471. }
  472. waitForExpectations(timeout: timeout, handler: nil)
  473. // Then
  474. XCTAssertNotNil(response?.request)
  475. XCTAssertNotNil(response?.response)
  476. XCTAssertNotNil(response?.data)
  477. XCTAssertEqual(response?.result.isSuccess, true)
  478. XCTAssertNotNil(response?.metrics)
  479. }
  480. func testThatTryMapErrorCatchesTransformationError() {
  481. // Given
  482. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  483. let expectation = self.expectation(description: "request should fail")
  484. var response: DataResponse<Data, Error>?
  485. // When
  486. AF.request(urlString).responseData { resp in
  487. response = resp.tryMapError { _ in try TransformationError.error.alwaysFails() }
  488. expectation.fulfill()
  489. }
  490. waitForExpectations(timeout: timeout, handler: nil)
  491. // Then
  492. XCTAssertNotNil(response?.request)
  493. XCTAssertNil(response?.response)
  494. XCTAssertNil(response?.data)
  495. XCTAssertEqual(response?.result.isFailure, true)
  496. if let error = response?.result.error {
  497. XCTAssertTrue(error is TransformationError)
  498. } else {
  499. XCTFail("tryMapError should catch the transformation error")
  500. }
  501. XCTAssertNotNil(response?.metrics)
  502. }
  503. func testThatTryMapErrorTransformsError() {
  504. // Given
  505. let urlString = "https://invalid-url-here.org/this/does/not/exist"
  506. let expectation = self.expectation(description: "request should fail")
  507. var response: DataResponse<Data, Error>?
  508. // When
  509. AF.request(urlString).responseData { resp in
  510. response = resp.tryMapError { TestError.error(error: $0) }
  511. expectation.fulfill()
  512. }
  513. waitForExpectations(timeout: timeout, handler: nil)
  514. // Then
  515. XCTAssertNotNil(response?.request)
  516. XCTAssertNil(response?.response)
  517. XCTAssertNil(response?.data)
  518. XCTAssertEqual(response?.result.isFailure, true)
  519. guard let error = response?.error as? TestError, case .error = error else { XCTFail(); return }
  520. XCTAssertNotNil(response?.metrics)
  521. }
  522. }