From 2727ad0a47b3b6bf3b5ab676bbfc64b3ebb31e77 Mon Sep 17 00:00:00 2001 From: Marcos Amorim Date: Fri, 11 Nov 2022 15:12:12 -0300 Subject: [PATCH 1/4] =?UTF-8?q?Cria=C3=A7=C3=A3o=20do=20NetworkClientSpy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Test Doubles/NetworkClientSpy.swift | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift index fecc4ab..2d223e3 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift +++ b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift @@ -1 +1,20 @@ import Foundation + +@testable import FinanceApp + +class NetWorkClientSpy: NetworkClientProtocol { + + + private(set) var performRequestCalled: Bool = false + private(set) var performRequestCallCount: Int = 0 + private(set) var performRequestURL: URL? + var performRequestCompletionDataToBeReturned: Data? + + func performRequest(with url: URL, completion: @escaping (Data?) -> ()) { + performRequestCalled = true + performRequestCallCount += 1 + performRequestURL = url + completion(performRequestCompletionDataToBeReturned) + } + +} From cb3eb03001b2665bcc5d1bd05fa3c843ea6d15ab Mon Sep 17 00:00:00 2001 From: MarcosAmorimBRQ <117674243+MarcosAmorimBRQ@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:09:22 -0300 Subject: [PATCH 2/4] Update solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift Co-authored-by: Leonardo <42387881+leocoout@users.noreply.github.com> --- .../FinanceAppTests/Test Doubles/NetworkClientSpy.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift index 2d223e3..f8c23a3 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift +++ b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift @@ -2,7 +2,7 @@ import Foundation @testable import FinanceApp -class NetWorkClientSpy: NetworkClientProtocol { +final class NetworkClientSpy: NetworkClientProtocol { private(set) var performRequestCalled: Bool = false From ac37debb55543c2610f5c7be10ab9322fa4d1d67 Mon Sep 17 00:00:00 2001 From: MarcosAmorimBRQ <117674243+MarcosAmorimBRQ@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:09:36 -0300 Subject: [PATCH 3/4] Update solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift Co-authored-by: Leonardo <42387881+leocoout@users.noreply.github.com> --- .../FinanceAppTests/Test Doubles/NetworkClientSpy.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift index f8c23a3..aabe7fc 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift +++ b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/NetworkClientSpy.swift @@ -4,7 +4,6 @@ import Foundation final class NetworkClientSpy: NetworkClientProtocol { - private(set) var performRequestCalled: Bool = false private(set) var performRequestCallCount: Int = 0 private(set) var performRequestURL: URL? From aaadc55291dc4a9ed974780882ca92fabad98238 Mon Sep 17 00:00:00 2001 From: Marcos Amorim Date: Mon, 21 Nov 2022 14:47:48 -0300 Subject: [PATCH 4/4] Testes do performRequest usando URLSessionSpy --- .../FinanceApp.xcodeproj/project.pbxproj | 4 + .../FinanceApp/Service/NetworkClient.swift | 8 +- .../FinanceAppTests/NetworkClientTests.swift | 74 +++++++++++++++++++ .../Test Doubles/URLSessionSpy.swift | 33 +++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 solutions/devsprint-brq-testes-ios-1/FinanceAppTests/NetworkClientTests.swift diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceApp.xcodeproj/project.pbxproj b/solutions/devsprint-brq-testes-ios-1/FinanceApp.xcodeproj/project.pbxproj index 12242ac..e78bd17 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceApp.xcodeproj/project.pbxproj +++ b/solutions/devsprint-brq-testes-ios-1/FinanceApp.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 33A58977292A7FE500E83449 /* NetworkClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33A58976292A7FE500E83449 /* NetworkClientTests.swift */; }; 4FE21AB929196913003C8ADA /* AccountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE21AB829196913003C8ADA /* AccountTests.swift */; }; 4FE21ABC29196968003C8ADA /* DispatchQueueSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE21ABB29196968003C8ADA /* DispatchQueueSpy.swift */; }; 4FE21ABE29196989003C8ADA /* NetworkClientSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE21ABD29196989003C8ADA /* NetworkClientSpy.swift */; }; @@ -78,6 +79,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 33A58976292A7FE500E83449 /* NetworkClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkClientTests.swift; sourceTree = ""; }; 4FE21AB829196913003C8ADA /* AccountTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTests.swift; sourceTree = ""; }; 4FE21ABB29196968003C8ADA /* DispatchQueueSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueueSpy.swift; sourceTree = ""; }; 4FE21ABD29196989003C8ADA /* NetworkClientSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkClientSpy.swift; sourceTree = ""; }; @@ -219,6 +221,7 @@ 4FE21AC3291969CE003C8ADA /* ContactListViewTests.swift */, 4FE21AC1291969BF003C8ADA /* ActivityListViewTests.swift */, 988BA51428D0EF820078896C /* HomeViewModelTests.swift */, + 33A58976292A7FE500E83449 /* NetworkClientTests.swift */, ); path = FinanceAppTests; sourceTree = ""; @@ -546,6 +549,7 @@ 988BA51528D0EF820078896C /* HomeViewModelTests.swift in Sources */, 988BA51328D0EF760078896C /* ActivityDetailsViewModelTests.swift in Sources */, 988BA50F28D0EF030078896C /* HomeDataTests.swift in Sources */, + 33A58977292A7FE500E83449 /* NetworkClientTests.swift in Sources */, 988BA51128D0EF330078896C /* FinanceServiceTests.swift in Sources */, 4FE21AB929196913003C8ADA /* AccountTests.swift in Sources */, 988BA50B28D0EE740078896C /* UITableViewCellExtensionsTests.swift in Sources */, diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceApp/Service/NetworkClient.swift b/solutions/devsprint-brq-testes-ios-1/FinanceApp/Service/NetworkClient.swift index 40856ae..d91d1eb 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceApp/Service/NetworkClient.swift +++ b/solutions/devsprint-brq-testes-ios-1/FinanceApp/Service/NetworkClient.swift @@ -13,12 +13,18 @@ protocol NetworkClientProtocol { } final class NetworkClient: NetworkClientProtocol { + + private let urlSession: URLSession + + init(urlSession: URLSession) { + self.urlSession = urlSession + } func performRequest(with url: URL, completion: @escaping (Data?) -> ()) { let request = URLRequest(url: url) - let task = URLSession.shared.dataTask(with: request) { data, response, error in + let task = urlSession.dataTask(with: request) { data, response, error in if let _ = error { completion(nil) diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/NetworkClientTests.swift b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/NetworkClientTests.swift new file mode 100644 index 0000000..a45d4b2 --- /dev/null +++ b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/NetworkClientTests.swift @@ -0,0 +1,74 @@ +// +// NetworkClientTests.swift +// FinanceAppTests +// +// Created by Marcos Amorim Rossi de Carvalho on 20/11/22. +// + +import Foundation +import XCTest + +@testable import FinanceApp + +class NetworkClientTests: XCTestCase { + + enum MyError: Error { + case genericError + } + + private var urlSessionSpy = URLSessionSpy() + private lazy var sut = NetworkClient(urlSession: self.urlSessionSpy) + + var mockedJson = +""" +{ + "balance": 1, + "savings": 2, + "spendings": 3 +} +""".data(using: .utf8) + + func test_performRequest_gotCalledCorrectly() { + let urlToBePassed = URL(string: "https://www.notion.so/devpass/")! + + sut.performRequest(with: urlToBePassed, completion: { + _ in + XCTAssertTrue(self.urlSessionSpy.dataTaskCalled) + }) + + } + + func test_performRequest_shouldReturnCorrectData() { + let urlToBePassed = URL(string: "https://www.notion.so/devpass/")! + urlSessionSpy.setData(data: mockedJson!) + + sut.performRequest(with: urlToBePassed, completion: { + data in + XCTAssertEqual(data, self.mockedJson) + }) + + } + + func test_performRequest_shouldReturnNilData() { + let urlToBePassed = URL(string: "https://www.notion.so/devpass/")! + + sut.performRequest(with: urlToBePassed, completion: { + data in + XCTAssertNil(data) + }) + + } + + func test_performRequest_whenErrorAndDataAreNotNil_shouldReturnNilData() { + let urlToBePassed = URL(string: "https://www.notion.so/devpass/")! + urlSessionSpy.setData(data: mockedJson!) + urlSessionSpy.setError(error: MyError.genericError) + + sut.performRequest(with: urlToBePassed, completion: { + data in + XCTAssertNil(data) + }) + + } + +} diff --git a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/URLSessionSpy.swift b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/URLSessionSpy.swift index fecc4ab..9b2ed79 100644 --- a/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/URLSessionSpy.swift +++ b/solutions/devsprint-brq-testes-ios-1/FinanceAppTests/Test Doubles/URLSessionSpy.swift @@ -1 +1,34 @@ import Foundation + +final class URLSessionSpy: URLSession { + + private(set) var dataTaskCalled: Bool = false + private(set) var dataTaskData: Data? + private(set) var dataTaskResponse: URLResponse? + private(set) var dataTaskError: Error? + + override func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { + dataTaskCalled = true + completionHandler(dataTaskData, dataTaskResponse, dataTaskError) + return URLSessionDataTaskSpy() + } + + func setData(data: Data) { + dataTaskData = data + } + + func setResponse(response: URLResponse) { + dataTaskResponse = response + } + + func setError(error: Error) { + dataTaskError = error + } +} + +final class URLSessionDataTaskSpy: URLSessionDataTask { + + override func resume() { + + } +}