Skip to content

Commit a49299f

Browse files
Refactor MockNetworkSession so that we can change response per request
1 parent 93d98d8 commit a49299f

File tree

8 files changed

+176
-40
lines changed

8 files changed

+176
-40
lines changed

tests/common/CommonMocks.swift

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,40 @@ class MockNetworkSession: NetworkSessionProtocol {
174174
private var canceled = false
175175
}
176176

177-
var urlPatternDataMapping: [String: Data?]?
178-
var delay: TimeInterval
177+
struct MockResponse {
178+
let statusCode: Int
179+
let data: Data?
180+
let delay: TimeInterval
181+
let error: Error?
182+
let headerFields: [String: String]?
183+
184+
init(statusCode: Int = MockNetworkSession.defaultStatus,
185+
data: Data? = MockNetworkSession.defaultData,
186+
delay: TimeInterval = 0.0,
187+
error: Error? = nil,
188+
headerFields: [String: String]? = MockNetworkSession.defaultHeaderFields) {
189+
self.statusCode = statusCode
190+
self.data = data
191+
self.delay = delay
192+
self.error = error
193+
self.headerFields = headerFields
194+
}
195+
196+
func toUrlResponse(url: URL) -> URLResponse? {
197+
HTTPURLResponse(url: url,
198+
statusCode: statusCode,
199+
httpVersion: MockNetworkSession.defaultHttpVersion,
200+
headerFields: headerFields)
201+
}
202+
}
203+
204+
var responseCallback: ((URL) -> MockResponse?)?
205+
179206
var requests = [URLRequest]()
180207
var callback: ((Data?, URLResponse?, Error?) -> Void)?
181208
var requestCallback: ((URLRequest) -> Void)?
182209

183-
var statusCode: Int
184-
var error: Error?
185-
186-
convenience init(statusCode: Int = 200, delay: TimeInterval = 0.0) {
210+
convenience init(statusCode: Int = MockNetworkSession.defaultStatus, delay: TimeInterval = 0.0) {
187211
self.init(statusCode: statusCode,
188212
data: [:].toJsonData(),
189213
delay: delay,
@@ -198,31 +222,42 @@ class MockNetworkSession: NetworkSessionProtocol {
198222
}
199223

200224
convenience init(statusCode: Int, data: Data?, delay: TimeInterval = 0.0, error: Error? = nil) {
201-
self.init(statusCode: statusCode, urlPatternDataMapping: [".*": data], delay: delay, error: error)
225+
let mockResponse = MockResponse(statusCode: statusCode,
226+
data: data,
227+
delay: delay,
228+
error: error)
229+
self.init(mapping: [".*": mockResponse])
230+
}
231+
232+
init(mapping: [String: MockResponse?]?) {
233+
self.responseCallback = { url in
234+
MockNetworkSession.response(for: url.absoluteString, inMapping: mapping)
235+
}
202236
}
203237

204-
init(statusCode: Int,
205-
urlPatternDataMapping: [String: Data?]?,
206-
delay: TimeInterval = 0.0,
207-
error: Error? = nil) {
208-
self.statusCode = statusCode
209-
self.urlPatternDataMapping = urlPatternDataMapping
210-
self.delay = delay
211-
self.error = error
238+
init(responseCallback: ((URL) -> MockResponse?)?) {
239+
self.responseCallback = responseCallback
212240
}
213241

214242
func makeRequest(_ request: URLRequest, completionHandler: @escaping NetworkSessionProtocol.CompletionHandler) {
243+
let mockResponse = self.mockResponse(for: request.url)
244+
215245
let block = {
216246
self.requests.append(request)
217247
self.requestCallback?(request)
218-
let response = HTTPURLResponse(url: request.url!, statusCode: self.statusCode, httpVersion: "HTTP/1.1", headerFields: [:])
219-
let data = self.data(for: request.url?.absoluteString)
220-
completionHandler(data, response, self.error)
221-
222-
self.callback?(data, response, self.error)
248+
if let mockResponse = mockResponse {
249+
let response = mockResponse.toUrlResponse(url: request.url!)
250+
completionHandler(mockResponse.data, response, mockResponse.error)
251+
self.callback?(mockResponse.data, response, mockResponse.error)
252+
} else {
253+
let response = Self.defaultURLResponse(forUrl: request.url!)
254+
completionHandler(Self.defaultData, response, nil)
255+
self.callback?(Self.defaultData, response, nil)
256+
}
223257
}
224258

225-
if delay == 0 {
259+
let delay = mockResponse?.delay ?? 0
260+
if delay == 0 {
226261
DispatchQueue.main.async {
227262
block()
228263
}
@@ -234,14 +269,24 @@ class MockNetworkSession: NetworkSessionProtocol {
234269
}
235270

236271
func makeDataRequest(with url: URL, completionHandler: @escaping NetworkSessionProtocol.CompletionHandler) {
272+
let mockResponse = self.mockResponse(for: url)
273+
237274
let block = {
238-
let response = HTTPURLResponse(url: url, statusCode: self.statusCode, httpVersion: "HTTP/1.1", headerFields: [:])
239-
let data = self.data(for: url.absoluteString)
240-
completionHandler(data, response, self.error)
241-
242-
self.callback?(data, response, self.error)
275+
if let mockResponse = mockResponse {
276+
let response = mockResponse.toUrlResponse(url: url)
277+
completionHandler(mockResponse.data, response, mockResponse.error)
278+
self.callback?(mockResponse.data, response, mockResponse.error)
279+
} else {
280+
let response = HTTPURLResponse(url: url,
281+
statusCode: Self.defaultStatus,
282+
httpVersion: Self.defaultHttpVersion,
283+
headerFields: Self.defaultHeaderFields)
284+
completionHandler(nil, response, nil)
285+
self.callback?(nil, response, nil)
286+
}
243287
}
244288

289+
let delay = mockResponse?.delay ?? 0
245290
if delay == 0 {
246291
DispatchQueue.main.async {
247292
block()
@@ -266,12 +311,31 @@ class MockNetworkSession: NetworkSessionProtocol {
266311
static func json(fromData data: Data) -> [AnyHashable: Any] {
267312
try! JSONSerialization.jsonObject(with: data, options: []) as! [AnyHashable: Any]
268313
}
314+
315+
private static let defaultStatus = 200
316+
private static let defaultData = [:].toJsonData()
317+
private static let defaultHttpVersion = "HTTP/1.1"
318+
private static let defaultHeaderFields: [String: String] = [:]
269319

270-
private func data(for urlAbsoluteString: String?) -> Data? {
320+
private static func defaultURLResponse(forUrl url: URL) -> URLResponse? {
321+
HTTPURLResponse(url: url,
322+
statusCode: Self.defaultStatus,
323+
httpVersion: Self.defaultHttpVersion,
324+
headerFields: Self.defaultHeaderFields)
325+
}
326+
327+
private func mockResponse(for url: URL?) -> MockResponse? {
328+
guard let url = url else {
329+
return nil
330+
}
331+
return responseCallback?(url)
332+
}
333+
334+
private static func response(for urlAbsoluteString: String?, inMapping mapping: [String: MockResponse?]?) -> MockResponse? {
271335
guard let urlAbsoluteString = urlAbsoluteString else {
272336
return nil
273337
}
274-
guard let mapping = urlPatternDataMapping else {
338+
guard let mapping = mapping else {
275339
return nil
276340
}
277341

tests/hosting-apps/inbox-ui-tests-app/AppDelegate.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2424

2525
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
2626
mockInAppFetcher = MockInAppFetcher()
27-
mockNetworkSession = MockNetworkSession(statusCode: 200, urlPatternDataMapping: createUrlToDataMapper())
27+
mockNetworkSession = MockNetworkSession(mapping: createUrlToResponseMapper())
2828
mockNetworkSession.requestCallback = { request in
2929
self.logRequest(request: request)
3030
}
@@ -112,9 +112,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
112112
return FileManager.default.contents(atPath: path)!
113113
}
114114

115-
private func createUrlToDataMapper() -> [String: Data?] {
116-
var mapper = [String: Data?]()
117-
mapper[#"mocha.png"#] = loadData(from: "mocha", withExtension: "png")
115+
private func createUrlToResponseMapper() -> [String: MockNetworkSession.MockResponse?] {
116+
var mapper = [String: MockNetworkSession.MockResponse?]()
117+
mapper[#"mocha.png"#] = MockNetworkSession.MockResponse(data: loadData(from: "mocha", withExtension: "png"))
118118
mapper[".*"] = nil
119119
return mapper
120120
}

tests/offline-events-tests/NetworkConnectivityManagerTests.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ class NetworkConnectivityManagerTests: XCTestCase {
9696

9797
// check that status is offline when there is network error
9898
let expectation1 = expectation(description: "ConnectivityManager: check status change on network error")
99-
networkSession.error = IterableError.general(description: "Mock error")
99+
networkSession.responseCallback = { _ in
100+
MockNetworkSession.MockResponse(error: IterableError.general(description: "Mock error"))
101+
}
100102
manager.connectivityChangedCallback = { connected in
101103
XCTAssertFalse(connected)
102104
expectation1.fulfill()
@@ -110,14 +112,16 @@ class NetworkConnectivityManagerTests: XCTestCase {
110112
XCTAssertTrue(connected)
111113
expectation2.fulfill()
112114
}
113-
networkSession.error = nil
115+
networkSession.responseCallback = nil
114116
wait(for: [expectation2], timeout: 10.0)
115117

116118
// check that status does not change once manager is stopped
117119
let expectation3 = expectation(description: "ConnectivityManager: no status change when stopped")
118120
expectation3.isInverted = true
119121
manager.stop()
120-
networkSession.error = IterableError.general(description: "Mock error")
122+
networkSession.responseCallback = { _ in
123+
MockNetworkSession.MockResponse(error: IterableError.general(description: "Mock error"))
124+
}
121125
manager.connectivityChangedCallback = { connected in
122126
XCTAssertTrue(connected)
123127
expectation3.fulfill()
@@ -154,7 +158,9 @@ class NetworkConnectivityManagerTests: XCTestCase {
154158
XCTAssertFalse(connected)
155159
expectation1.fulfill()
156160
}
157-
networkSession.error = IterableError.general(description: "Mock error")
161+
networkSession.responseCallback = { _ in
162+
MockNetworkSession.MockResponse(error: IterableError.general(description: "Mock error"))
163+
}
158164

159165
wait(for: [expectation1], timeout: 10.0)
160166
}

tests/offline-events-tests/RequestHandlerTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,3 +1175,15 @@ extension RequestHandlerTests: AuthProvider {
11751175
Auth(userId: nil, email: "[email protected]", authToken: nil)
11761176
}
11771177
}
1178+
1179+
fileprivate extension MockNetworkSession {
1180+
convenience init(statusCode: Int, urlPatternDataMapping: [String: Data?]?) {
1181+
let mapping = urlPatternDataMapping?.mapValues { data in
1182+
MockNetworkSession.MockResponse(statusCode: statusCode,
1183+
data: data,
1184+
delay: 0.0,
1185+
error: nil)
1186+
}
1187+
self.init(mapping: mapping)
1188+
}
1189+
}

tests/offline-events-tests/TaskRunnerTests.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,7 @@ class TaskRunnerTests: XCTestCase {
198198
verifyNoTaskIsExecuted(notificationCenter, forInterval: 1.0)
199199

200200
// set network status back to normal
201-
networkSession.statusCode = 200
202-
networkSession.error = nil
201+
networkSession.responseCallback = nil
203202

204203
verifyTaskIsExecuted(notificationCenter, withinInterval: 10.0)
205204

tests/unit-tests/AuthTests.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,61 @@ class AuthTests: XCTestCase {
753753
wait(for: [condition1], timeout: testExpectationTimeoutForInverted)
754754
}
755755

756+
func testA() throws {
757+
758+
let expectation1 = expectation(description: #function)
759+
760+
var callNumber = 0
761+
let authDelegate = createAuthDelegate {
762+
callNumber += 1
763+
if callNumber == 1 {
764+
return nil
765+
} else {
766+
return "some-auth-token"
767+
}
768+
}
769+
770+
let config = IterableConfig()
771+
config.authDelegate = authDelegate
772+
773+
let networkSession = MockJwtResponseNetworkSession()
774+
775+
let api = InternalIterableAPI.initializeForTesting(
776+
config: config,
777+
networkSession: networkSession
778+
)
779+
api.userId = "some-user-id"
780+
api.track("some-event").onSuccess { _ in
781+
print("success")
782+
expectation1.fulfill()
783+
}.onError { error in
784+
print("error, \(error)")
785+
expectation1.fulfill()
786+
}
787+
wait(for: [expectation1], timeout: testExpectationTimeout)
788+
789+
class MockJwtResponseNetworkSession: NetworkSessionProtocol {
790+
var callNumber = 0
791+
func makeRequest(_ request: URLRequest, completionHandler: @escaping CompletionHandler) {
792+
callNumber += 1
793+
let data = callNumber == 1 ? [JsonKey.Response.iterableCode: JsonValue.Code.invalidJwtPayload].toJsonData() : nil
794+
let response = HTTPURLResponse(url: request.url!,
795+
statusCode: callNumber == 1 ? 401 : 200,
796+
httpVersion: "HTTP/1.1",
797+
headerFields: [:])
798+
completionHandler(data, response, nil)
799+
}
800+
801+
func makeDataRequest(with url: URL, completionHandler: @escaping CompletionHandler) {
802+
fatalError()
803+
}
804+
805+
func createDataTask(with url: URL, completionHandler: @escaping CompletionHandler) -> DataTaskProtocol {
806+
fatalError()
807+
}
808+
}
809+
}
810+
756811
// MARK: - Private
757812

758813
class DefaultAuthDelegate: IterableAuthDelegate {

tests/unit-tests/InAppPersistenceTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class InAppPersistenceTests: XCTestCase {
2424
}
2525

2626
func testInboxMetadataDecodingEncoding() {
27-
let title = "TITLE!!!"
27+
let title = "TITLE"
2828
let subtitle = "subtitle :)"
2929
let icon = "picture.jpg"
3030

tests/unit-tests/InboxMessageViewModelTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class InboxMessageViewModelTests: XCTestCase {
1010
func testModel() {
1111
let testCreationDate = Date()
1212

13-
let title = "TITLE!!!!!"
13+
let title = "TITLE"
1414
let subtitle = "a prelude of the journey to the road to the goal"
1515
let icon = "https://imageurl.com/thingy"
1616

0 commit comments

Comments
 (0)