From d5b192c894e9cbe86eda1f7ca54762d5face76ad Mon Sep 17 00:00:00 2001 From: loinsir Date: Thu, 11 Jan 2024 00:32:04 +0900 Subject: [PATCH 1/4] =?UTF-8?q?:white=5Fcheck=5Fmark:=20SignUpInteractorTe?= =?UTF-8?q?sts=20=EC=B6=94=EA=B0=80,=20Mock=20Worker=20final=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 25 ++- .../Scenes/SignUpScene/SignUpInteractor.swift | 38 ++--- .../Layover/Scenes/SignUpViewController.swift | 8 +- .../Workers/Mocks/MockSignUpWorker.swift | 8 +- .../Mocks/Workers/MockUserWorker.swift | 2 +- .../Scenes/SignUp/SignUpInteractorTests.swift | 159 ++++++++++++++++++ .../Scenes/SignUp/SignUpPresenterTests.swift | 62 +++++++ .../SignUp/SignUpViewControllerTests.swift | 84 +++++++++ .../Scenes/SignUp/SignUpWorkerTests.swift | 50 ++++++ 9 files changed, 404 insertions(+), 32 deletions(-) create mode 100644 iOS/Layover/LayoverTests/Scenes/SignUp/SignUpInteractorTests.swift create mode 100644 iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift create mode 100644 iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift create mode 100644 iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index 1903fab..b90f863 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -113,6 +113,10 @@ 19AE482A2B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE48292B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift */; }; 19AE482C2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE482B2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift */; }; 19AE482E2B2A24C700DD4612 /* URL+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE482D2B2A24C700DD4612 /* URL+.swift */; }; + 19B665D82B4EEDDD0083E63C /* SignUpViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */; }; + 19B665D92B4EEDDD0083E63C /* SignUpWorkerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */; }; + 19B665DA2B4EEDDD0083E63C /* SignUpInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */; }; + 19B665DB2B4EEDDD0083E63C /* SignUpPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */; }; 19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */; }; 19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */; }; 19E79AC02B0A85D0009EA9ED /* LoopingPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E79ABF2B0A85D0009EA9ED /* LoopingPlayerView.swift */; }; @@ -368,6 +372,10 @@ 19AE48292B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSAssetResourceLoaderDelegate.swift; sourceTree = ""; }; 19AE482B2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSSliceResourceLoader.swift; sourceTree = ""; }; 19AE482D2B2A24C700DD4612 /* URL+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+.swift"; sourceTree = ""; }; + 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpViewControllerTests.swift; sourceTree = ""; }; + 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpWorkerTests.swift; sourceTree = ""; }; + 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpInteractorTests.swift; sourceTree = ""; }; + 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpPresenterTests.swift; sourceTree = ""; }; 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = ""; }; 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainStored.swift; sourceTree = ""; }; 19E79ABF2B0A85D0009EA9ED /* LoopingPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopingPlayerView.swift; sourceTree = ""; }; @@ -619,6 +627,7 @@ 194C21C72B1DF09B00C62645 /* Scenes */ = { isa = PBXGroup; children = ( + 19B665D32B4EEDDD0083E63C /* SignUp */, 19AE481D2B29D02700DD4612 /* EditProfile */, 19AE48122B28C2A800DD4612 /* Setting */, 192513632B26F7BB001533FA /* TagPlayList */, @@ -793,6 +802,17 @@ path = HLSResourceLoader; sourceTree = ""; }; + 19B665D32B4EEDDD0083E63C /* SignUp */ = { + isa = PBXGroup; + children = ( + 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */, + 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */, + 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */, + 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */, + ); + path = SignUp; + sourceTree = ""; + }; 19BB8A572B07BEE30070B922 /* UIComponents */ = { isa = PBXGroup; children = ( @@ -1436,7 +1456,6 @@ FC2511AB2B04EA6B004717BC /* MapConfigurator.swift in Sources */, 1945523B2B05258200299768 /* HomeConfigurator.swift in Sources */, FCF19BE22B2A4088003002E0 /* AVFileType+.swift in Sources */, - FC5BE11D2B148D160036366D /* EditProfileWorker.swift in Sources */, 19A1693A2B17BCC400DB34C0 /* MemberDTO.swift in Sources */, 194551F62B037F2D00299768 /* LoginViewController.swift in Sources */, FC767FA52B125F430088CF9B /* UIViewController+.swift in Sources */, @@ -1600,11 +1619,15 @@ 1925136D2B26F84E001533FA /* MockTagPlayListWorker.swift in Sources */, 19AE481A2B28C2B700DD4612 /* SettingPresenterTests.swift in Sources */, 19AE48172B28C2B700DD4612 /* SettingViewControllerTests.swift in Sources */, + 19B665DA2B4EEDDD0083E63C /* SignUpInteractorTests.swift in Sources */, + 19B665DB2B4EEDDD0083E63C /* SignUpPresenterTests.swift in Sources */, + 19B665D82B4EEDDD0083E63C /* SignUpViewControllerTests.swift in Sources */, 194C21C32B1DEE6B00C62645 /* HomeViewControllerTests.swift in Sources */, 192513692B26F7CE001533FA /* TagPlayListInteractorTests.swift in Sources */, 19AE48232B29D03D00DD4612 /* EditProfileInteractorTests.swift in Sources */, 194C21CC2B1DF39200C62645 /* MockHomeWorker.swift in Sources */, FC4E0C0E2B282AE500152596 /* UploadPostWorkerTests.swift in Sources */, + 19B665D92B4EEDDD0083E63C /* SignUpWorkerTests.swift in Sources */, FC4E0C112B28595200152596 /* MockUploadPostWorker.swift in Sources */, FC4E0C0D2B282AE500152596 /* UploadPostInteractorTests.swift in Sources */, ); diff --git a/iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift index dd98c7d..3177943 100644 --- a/iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift +++ b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift @@ -10,8 +10,8 @@ import UIKit protocol SignUpBusinessLogic { func validateNickname(with request: SignUpModels.ValidateNickname.Request) - func checkDuplication(with request: SignUpModels.CheckDuplication.Request) - func signUp(with request: SignUpModels.SignUp.Request) + func checkDuplication(with request: SignUpModels.CheckDuplication.Request) async + func signUp(with request: SignUpModels.SignUp.Request) async } protocol SignUpDataStore: AnyObject { @@ -40,33 +40,29 @@ final class SignUpInteractor: SignUpBusinessLogic, SignUpDataStore { presenter?.presentNicknameValidation(with: SignUpModels.ValidateNickname.Response(nicknameState: response)) } - func checkDuplication(with request: SignUpModels.CheckDuplication.Request) { - Task { - let response = await userWorker?.checkNotDuplication(for: request.nickname) - await MainActor.run { - presenter?.presentNicknameDuplication(with: SignUpModels.CheckDuplication.Response(isValid: response ?? false)) - } + func checkDuplication(with request: SignUpModels.CheckDuplication.Request) async { + let response = await userWorker?.checkNotDuplication(for: request.nickname) + await MainActor.run { + presenter?.presentNicknameDuplication(with: SignUpModels.CheckDuplication.Response(isValid: response ?? false)) } } // MARK: - UseCase: SignUp - func signUp(with request: SignUpModels.SignUp.Request) { + func signUp(with request: SignUpModels.SignUp.Request) async { guard let signUpType, let socialToken else { return } - Task { - switch signUpType { - case .kakao: - if await signUpWorker?.signUp(withKakao: socialToken, username: request.nickname) == true { - await MainActor.run { - presenter?.presentSignUpSuccess() - } + switch signUpType { + case .kakao: + if await signUpWorker?.signUp(withKakao: socialToken, username: request.nickname) == true { + await MainActor.run { + presenter?.presentSignUpSuccess() } - case .apple: - if await signUpWorker?.signUp(withApple: socialToken, username: request.nickname) == true { - await MainActor.run { - presenter?.presentSignUpSuccess() - } + } + case .apple: + if await signUpWorker?.signUp(withApple: socialToken, username: request.nickname) == true { + await MainActor.run { + presenter?.presentSignUpSuccess() } } } diff --git a/iOS/Layover/Layover/Scenes/SignUpViewController.swift b/iOS/Layover/Layover/Scenes/SignUpViewController.swift index fe01214..dab52af 100644 --- a/iOS/Layover/Layover/Scenes/SignUpViewController.swift +++ b/iOS/Layover/Layover/Scenes/SignUpViewController.swift @@ -137,7 +137,9 @@ final class SignUpViewController: BaseViewController { @objc private func checkDuplicateNicknameButtonDidTap(_ sender: UIButton) { guard let nickname = nicknameTextfield.text else { return } checkDuplicateNicknameButton.isEnabled = false - interactor?.checkDuplication(with: SignUpModels.CheckDuplication.Request(nickname: nickname)) + Task { + await interactor?.checkDuplication(with: SignUpModels.CheckDuplication.Request(nickname: nickname)) + } } @objc private func popViewController() { @@ -146,7 +148,9 @@ final class SignUpViewController: BaseViewController { @objc private func signUpButtonDidTap(_ sender: UIButton) { guard let nickname = nicknameTextfield.text else { return } - interactor?.signUp(with: SignUpModels.SignUp.Request(nickname: nickname)) + Task { + await interactor?.signUp(with: SignUpModels.SignUp.Request(nickname: nickname)) + } } } diff --git a/iOS/Layover/Layover/Workers/Mocks/MockSignUpWorker.swift b/iOS/Layover/Layover/Workers/Mocks/MockSignUpWorker.swift index 2bfc300..6198cf3 100644 --- a/iOS/Layover/Layover/Workers/Mocks/MockSignUpWorker.swift +++ b/iOS/Layover/Layover/Workers/Mocks/MockSignUpWorker.swift @@ -9,7 +9,7 @@ import Foundation import OSLog -final class MockSignUpWorker { +class MockSignUpWorker: SignUpWorkerProtocol { // MARK: - Properties @@ -21,11 +21,6 @@ final class MockSignUpWorker { authManager: StubAuthManager())) { self.provider = provider } -} - -// MARK: - SignUpWorkerProtocol - -extension MockSignUpWorker: SignUpWorkerProtocol { func signUp(withKakao socialToken: String, username: String) async -> Bool { guard let mockFileLocation = Bundle.main.url(forResource: "LoginData", withExtension: "json"), @@ -86,5 +81,4 @@ extension MockSignUpWorker: SignUpWorkerProtocol { return false } } - } diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockUserWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockUserWorker.swift index 117dfb1..5faa754 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/MockUserWorker.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockUserWorker.swift @@ -9,7 +9,7 @@ import Foundation import OSLog -final class MockUserWorker: UserWorkerProtocol { +class MockUserWorker: UserWorkerProtocol { // MARK: - Properties diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpInteractorTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpInteractorTests.swift new file mode 100644 index 0000000..7d83d66 --- /dev/null +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpInteractorTests.swift @@ -0,0 +1,159 @@ +// +// SignUpInteractorTests.swift +// Layover +// +// Created by 김인환 on 1/6/24. +// Copyright (c) 2024 CodeBomber. All rights reserved. +// +// This file was generated by the Clean Swift Xcode Templates so +// you can apply clean architecture to your iOS and Mac projects, +// see http://clean-swift.com +// + +@testable import Layover +import XCTest + +final class SignUpInteractorTests: XCTestCase { + // MARK: Subject under test + + var sut: SignUpInteractor! + + typealias Models = SignUpModels + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + setupSignUpInteractor() + } + + // MARK: - Test setup + + func setupSignUpInteractor() { + sut = SignUpInteractor() + } + + // MARK: - Test doubles + + final class SignUpPresentationLogicSpy: SignUpPresentationLogic { + var presentSignUpSuccessDidCalled = false + var presentNicknameValidationDidCalled = false + var presentNicknameValidationResponse: Models.ValidateNickname.Response! + var presentNicknameDuplicationDidCalled = false + var presentNicknameDupllicationResponse: Models.CheckDuplication.Response! + + func presentSignUpSuccess() { + presentSignUpSuccessDidCalled = true + } + + func presentNicknameValidation(with response: Models.ValidateNickname.Response) { + presentNicknameValidationDidCalled = true + presentNicknameValidationResponse = response + } + + func presentNicknameDuplication(with response: Models.CheckDuplication.Response) { + presentNicknameDuplicationDidCalled = true + presentNicknameDupllicationResponse = response + } + } + + final class UserWorkerSpy: MockUserWorker { + var validateNicknameCalled = false + var checkNotDuplicationCalled = false + + override func validateNickname(_ nickname: String) -> NicknameState { + validateNicknameCalled = true + return super.validateNickname(nickname) + } + + override func checkNotDuplication(for userName: String) async -> Bool? { + checkNotDuplicationCalled = true + return await super.checkNotDuplication(for: userName) + } + } + + final class SignUpWorkerSpy: MockSignUpWorker { + var signUpWithKakaoCalled = false + var signUpWithAppleCalled = false + + override func signUp(withKakao token: String, username: String) async -> Bool { + signUpWithKakaoCalled = true + return await super.signUp(withKakao: token, username: username) + } + + override func signUp(withApple identityToken: String, username: String) async -> Bool { + signUpWithAppleCalled = true + return await super.signUp(withApple: identityToken, username: username) + } + } + + // MARK: - Tests + + func test_유효한_닉네임값으로_validateNickname을_호출하면_UserWorker를_통해_닉네임_유효성_검사를_요청하고_valid_결과를_presenter의_presentNicknameValidation를_호출한다() { + // arrange + let presenterSpy = SignUpPresentationLogicSpy() + sut.presenter = presenterSpy + let userWorkerSpy = UserWorkerSpy() + sut.userWorker = userWorkerSpy + + // act + sut.validateNickname(with: Models.ValidateNickname.Request(nickname: "안유진")) + + // assert + XCTAssertTrue(userWorkerSpy.validateNicknameCalled) + XCTAssertTrue(presenterSpy.presentNicknameValidationDidCalled) + XCTAssertNotNil(presenterSpy.presentNicknameValidationResponse.nicknameState) + } + + func test_checkDuplication을_호출하면_UserWorker를_통해_닉네임_중복_검사를_요청하고_결과를_presenter의_presentNicknameDuplication를_호출하여_전달한다() async { + // arrange + let presenterSpy = SignUpPresentationLogicSpy() + sut.presenter = presenterSpy + let userWorkerSpy = UserWorkerSpy() + sut.userWorker = userWorkerSpy + let signUpWorkerSpy = SignUpWorkerSpy() + sut.signUpWorker = signUpWorkerSpy + + // act + await sut.checkDuplication(with: Models.CheckDuplication.Request(nickname: "안유진")) + + // assert + XCTAssertTrue(userWorkerSpy.checkNotDuplicationCalled) + XCTAssertTrue(presenterSpy.presentNicknameDuplicationDidCalled) + XCTAssertNotNil(presenterSpy.presentNicknameDupllicationResponse.isValid) + } + + func test_카카오_signUp을_호출하면_SignUpWorker를_통해_회원가입을_요청하고_presenter의_presentSignUpSuccess를_호출한다() async { + // arrange + let presenterSpy = SignUpPresentationLogicSpy() + sut.presenter = presenterSpy + let signUpWorkerSpy = SignUpWorkerSpy() + signUpWorkerSpy.signUpWithKakaoCalled = true + sut.signUpWorker = signUpWorkerSpy + sut.signUpType = .kakao + sut.socialToken = "1234" + + // act + await sut.signUp(with: Models.SignUp.Request(nickname: "안유진")) + + // assert + XCTAssertTrue(presenterSpy.presentSignUpSuccessDidCalled) + } + + func test_애플_signUp을_호출하면_SignUpWorker를_통해_회원가입을_요청하고_presenter의_presentSignUpSuccess를_호출한다() async { + // arrange + let presenterSpy = SignUpPresentationLogicSpy() + sut.presenter = presenterSpy + let signUpWorkerSpy = SignUpWorkerSpy() + signUpWorkerSpy.signUpWithAppleCalled = true + sut.signUpWorker = signUpWorkerSpy + sut.signUpType = .apple + sut.socialToken = "1234" + + // act + await sut.signUp(with: Models.SignUp.Request(nickname: "안유진")) + + // assert + XCTAssertTrue(presenterSpy.presentSignUpSuccessDidCalled) + } +} diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift new file mode 100644 index 0000000..6f6e876 --- /dev/null +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift @@ -0,0 +1,62 @@ +//// +//// SignUpPresenterTests.swift +//// Layover +//// +//// Created by 김인환 on 1/6/24. +//// Copyright (c) 2024 CodeBomber. All rights reserved. +//// +//// This file was generated by the Clean Swift Xcode Templates so +//// you can apply clean architecture to your iOS and Mac projects, +//// see http://clean-swift.com +//// +// +//@testable import Layover +//import XCTest +// +//class SignUpPresenterTests: XCTestCase { +// // MARK: Subject under test +// +// var sut: SignUpPresenter! +// +// // MARK: - Test lifecycle +// +// override func setUp() { +// super.setUp() +// setupSignUpPresenter() +// } +// +// override func tearDown() { +// super.tearDown() +// } +// +// // MARK: - Test setup +// +// func setupSignUpPresenter() { +// sut = SignUpPresenter() +// } +// +// // MARK: - Test doubles +// +// class SignUpDisplayLogicSpy: SignUpDisplayLogic { +// var displaySomethingCalled = false +// +// func displaySomething(viewModel: SignUp.Something.ViewModel) { +// displaySomethingCalled = true +// } +// } +// +// // MARK: - Tests +// +// func testPresentSomething() { +// // Given +// let spy = SignUpDisplayLogicSpy() +// sut.viewController = spy +// let response = SignUp.Something.Response() +// +// // When +// sut.presentSomething(response: response) +// +// // Then +// XCTAssertTrue(spy.displaySomethingCalled, "presentSomething(response:) should ask the view controller to display the result") +// } +//} diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift new file mode 100644 index 0000000..85c1685 --- /dev/null +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift @@ -0,0 +1,84 @@ +//// +//// SignUpViewControllerTests.swift +//// Layover +//// +//// Created by 김인환 on 1/6/24. +//// Copyright (c) 2024 CodeBomber. All rights reserved. +//// +//// This file was generated by the Clean Swift Xcode Templates so +//// you can apply clean architecture to your iOS and Mac projects, +//// see http://clean-swift.com +//// +// +//@testable import Layover +//import XCTest +// +//class SignUpViewControllerTests: XCTestCase { +// // MARK: Subject under test +// +// var sut: SignUpViewController! +// var window: UIWindow! +// +// // MARK: - Test lifecycle +// +// override func setUp() { +// super.setUp() +// window = UIWindow() +// setupSignUpViewController() +// } +// +// override func tearDown() { +// window = nil +// super.tearDown() +// } +// +// // MARK: - Test setup +// +// func setupSignUpViewController() { +// let bundle = Bundle.main +// let storyboard = UIStoryboard(name: "Main", bundle: bundle) +// sut = storyboard.instantiateViewController(withIdentifier: "SignUpViewController") as! SignUpViewController +// } +// +// func loadView() { +// window.addSubview(sut.view) +// RunLoop.current.run(until: Date()) +// } +// +// // MARK: - Test doubles +// +// class SignUpBusinessLogicSpy: SignUpBusinessLogic { +// var doSomethingCalled = false +// +// func doSomething(request: SignUp.Something.Request) +// { +// doSomethingCalled = true +// } +// } +// +// // MARK: - Tests +// +// func testShouldDoSomethingWhenViewIsLoaded() { +// // Given +// let spy = SignUpBusinessLogicSpy() +// sut.interactor = spy +// +// // When +// loadView() +// +// // Then +// XCTAssertTrue(spy.doSomethingCalled, "viewDidLoad() should ask the interactor to do something") +// } +// +// func testDisplaySomething() { +// // Given +// let viewModel = SignUp.Something.ViewModel() +// +// // When +// loadView() +// sut.displaySomething(viewModel: viewModel) +// +// // Then +// //XCTAssertEqual(sut.nameTextField.text, "", "displaySomething(viewModel:) should update the name text field") +// } +//} diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift new file mode 100644 index 0000000..9152372 --- /dev/null +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift @@ -0,0 +1,50 @@ +// +// SignUpWorkerTests.swift +// Layover +// +// Created by 김인환 on 1/6/24. +// Copyright (c) 2024 CodeBomber. All rights reserved. +// +// This file was generated by the Clean Swift Xcode Templates so +// you can apply clean architecture to your iOS and Mac projects, +// see http://clean-swift.com +// + +@testable import Layover +import XCTest + +class SignUpWorkerTests: XCTestCase +{ + // MARK: Subject under test + + var sut: SignUpWorker! + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + setupSignUpWorker() + } + + override func tearDown() { + super.tearDown() + } + + // MARK: - Test setup + + func setupSignUpWorker() { + sut = SignUpWorker() + } + + // MARK: - Test doubles + + // MARK: - Tests + + func testSomething() { + // Given + + // When + + // Then + } +} From 9468a9ed1d183f22ce020c579dcefee19e72ca63 Mon Sep 17 00:00:00 2001 From: loinsir Date: Thu, 11 Jan 2024 02:08:35 +0900 Subject: [PATCH 2/4] =?UTF-8?q?:white=5Fcheck=5Fmark:=20SignUpPresenterTes?= =?UTF-8?q?ts=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scenes/SignUpScene/SignUpPresenter.swift | 2 +- .../Layover/Scenes/SignUpViewController.swift | 4 +- .../Scenes/SignUp/SignUpPresenterTests.swift | 198 +++++++++++++----- 3 files changed, 143 insertions(+), 61 deletions(-) diff --git a/iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift index 64a0c61..0cc3278 100644 --- a/iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift +++ b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift @@ -31,7 +31,7 @@ final class SignUpPresenter: SignUpPresentationLogic { func presentNicknameDuplication(with response: SignUpModels.CheckDuplication.Response) { let viewModel = Models.CheckDuplication.ViewModel(canSignUp: response.isValid) - viewController?.displayNickanmeDuplication(response: viewModel) + viewController?.displayNicknameDuplication(response: viewModel) } func presentSignUpSuccess() { diff --git a/iOS/Layover/Layover/Scenes/SignUpViewController.swift b/iOS/Layover/Layover/Scenes/SignUpViewController.swift index dab52af..bbaffa9 100644 --- a/iOS/Layover/Layover/Scenes/SignUpViewController.swift +++ b/iOS/Layover/Layover/Scenes/SignUpViewController.swift @@ -10,7 +10,7 @@ import UIKit protocol SignUpDisplayLogic: AnyObject { func displayNicknameValidation(response: SignUpModels.ValidateNickname.ViewModel) - func displayNickanmeDuplication(response: SignUpModels.CheckDuplication.ViewModel) + func displayNicknameDuplication(response: SignUpModels.CheckDuplication.ViewModel) func navigateToMain() } @@ -163,7 +163,7 @@ extension SignUpViewController: SignUpDisplayLogic { nicknameAlertLabel.textColor = .error } - func displayNickanmeDuplication(response: SignUpModels.CheckDuplication.ViewModel) { + func displayNicknameDuplication(response: SignUpModels.CheckDuplication.ViewModel) { nicknameAlertLabel.isHidden = false nicknameAlertLabel.text = response.alertDescription nicknameAlertLabel.textColor = response.canSignUp ? .correct : .error diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift index 6f6e876..dd92fb6 100644 --- a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpPresenterTests.swift @@ -1,62 +1,144 @@ -//// -//// SignUpPresenterTests.swift -//// Layover -//// -//// Created by 김인환 on 1/6/24. -//// Copyright (c) 2024 CodeBomber. All rights reserved. -//// -//// This file was generated by the Clean Swift Xcode Templates so -//// you can apply clean architecture to your iOS and Mac projects, -//// see http://clean-swift.com -//// // -//@testable import Layover -//import XCTest +// SignUpPresenterTests.swift +// Layover // -//class SignUpPresenterTests: XCTestCase { -// // MARK: Subject under test +// Created by 김인환 on 1/6/24. +// Copyright (c) 2024 CodeBomber. All rights reserved. // -// var sut: SignUpPresenter! +// This file was generated by the Clean Swift Xcode Templates so +// you can apply clean architecture to your iOS and Mac projects, +// see http://clean-swift.com // -// // MARK: - Test lifecycle -// -// override func setUp() { -// super.setUp() -// setupSignUpPresenter() -// } -// -// override func tearDown() { -// super.tearDown() -// } -// -// // MARK: - Test setup -// -// func setupSignUpPresenter() { -// sut = SignUpPresenter() -// } -// -// // MARK: - Test doubles -// -// class SignUpDisplayLogicSpy: SignUpDisplayLogic { -// var displaySomethingCalled = false -// -// func displaySomething(viewModel: SignUp.Something.ViewModel) { -// displaySomethingCalled = true -// } -// } -// -// // MARK: - Tests -// -// func testPresentSomething() { -// // Given -// let spy = SignUpDisplayLogicSpy() -// sut.viewController = spy -// let response = SignUp.Something.Response() -// -// // When -// sut.presentSomething(response: response) -// -// // Then -// XCTAssertTrue(spy.displaySomethingCalled, "presentSomething(response:) should ask the view controller to display the result") -// } -//} + +@testable import Layover +import XCTest + +final class SignUpPresenterTests: XCTestCase { + // MARK: Subject under test + + var sut: SignUpPresenter! + + typealias Models = SignUpModels + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + setupSignUpPresenter() + } + + // MARK: - Test setup + + func setupSignUpPresenter() { + sut = SignUpPresenter() + } + + // MARK: - Test doubles + + final class SignUpDisplayLogicSpy: SignUpDisplayLogic { + var displayNicknameValidationDidCalled = false + var displayNicknameValidationResponse: Models.ValidateNickname.ViewModel! + var displayNicknameDuplicationDidCalled = false + var displayNicknameDuplicationResponse: Models.CheckDuplication.ViewModel! + var navigateToMainDidCalled = false + + func displayNicknameValidation(response: Models.ValidateNickname.ViewModel) { + displayNicknameValidationDidCalled = true + displayNicknameValidationResponse = response + } + + func displayNicknameDuplication(response: Models.CheckDuplication.ViewModel) { + displayNicknameDuplicationDidCalled = true + displayNicknameDuplicationResponse = response + } + + func navigateToMain() { + navigateToMainDidCalled = true + } + } + + // MARK: - Tests + + func test_presentNicknameValidation가_호출되고_전달되는_nicknameState가_valid면_ViewController의_displayNicknameValidation이_호출되고_올바른_값이_전달된다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + let nicknameState = NicknameState.valid + + // act + sut.presentNicknameValidation(with: Models.ValidateNickname.Response(nicknameState: nicknameState)) + + // assert + XCTAssertTrue(spy.displayNicknameValidationDidCalled) + XCTAssertTrue(spy.displayNicknameValidationResponse.canCheckDuplication) + XCTAssertEqual(spy.displayNicknameValidationResponse.alertDescription, nicknameState.description) + } + + func test_presentNicknameValidation가_호출되고_전달되는_nicknameState가_invalidCharacter면_ViewController의_displayNicknameValidation이_호출되고_올바른_값이_전달된다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + let nicknameState = NicknameState.invalidCharacter + + // act + sut.presentNicknameValidation(with: Models.ValidateNickname.Response(nicknameState: nicknameState)) + + // assert + XCTAssertTrue(spy.displayNicknameValidationDidCalled) + XCTAssertFalse(spy.displayNicknameValidationResponse.canCheckDuplication) + XCTAssertEqual(spy.displayNicknameValidationResponse.alertDescription, nicknameState.description) + } + + func test_presentNicknameValidation가_호출되고_전달되는_nicknameState가_lessThan2GreaterThan8면_ViewController의_displayNicknameValidation이_호출되고_올바른_값이_전달된다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + let nicknameState = NicknameState.lessThan2GreaterThan8 + + // act + sut.presentNicknameValidation(with: Models.ValidateNickname.Response(nicknameState: .lessThan2GreaterThan8)) + + // assert + XCTAssertTrue(spy.displayNicknameValidationDidCalled) + XCTAssertFalse(spy.displayNicknameValidationResponse.canCheckDuplication) + XCTAssertEqual(spy.displayNicknameValidationResponse.alertDescription, nicknameState.description) + } + + func test_presentNicknameDuplication가_호출되면_ViewController의_displayNicknameDuplication이_호출되고_isValid_true값을_그대로_전달한다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + + // act + sut.presentNicknameDuplication(with: Models.CheckDuplication.Response(isValid: true)) + + // assert + XCTAssertTrue(spy.displayNicknameDuplicationDidCalled) + XCTAssertTrue(spy.displayNicknameDuplicationResponse.canSignUp) + } + + func test_presentNicknameDuplication가_호출되면_ViewController의_displayNicknameDuplication이_호출되고_전달받은_isValid_false값을_그대로_전달한다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + + // act + sut.presentNicknameDuplication(with: Models.CheckDuplication.Response(isValid: false)) + + // assert + XCTAssertTrue(spy.displayNicknameDuplicationDidCalled) + XCTAssertFalse(spy.displayNicknameDuplicationResponse.canSignUp) + } + + func test_presentSignUpSuccess가_호출되면_ViewController의_navigateToMain이_호출된다() { + // arrange + let spy = SignUpDisplayLogicSpy() + sut.viewController = spy + + // act + sut.presentSignUpSuccess() + + // assert + XCTAssertTrue(spy.navigateToMainDidCalled) + } +} From cd5a14922145e8704e58c7b1dd6b54a8e3c2bb14 Mon Sep 17 00:00:00 2001 From: loinsir Date: Thu, 11 Jan 2024 03:35:10 +0900 Subject: [PATCH 3/4] =?UTF-8?q?:white=5Fcheck=5Fmark:=20SignUpWorkerTests?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 4 + .../Mocks/Workers/MockSignUpWorker.swift | 85 ++++++++++ .../Scenes/SignUp/SignUpWorkerTests.swift | 151 ++++++++++++++++-- .../LayoverTests/Stubs/StubAuthManager.swift | 21 ++- 4 files changed, 248 insertions(+), 13 deletions(-) create mode 100644 iOS/Layover/LayoverTests/Mocks/Workers/MockSignUpWorker.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index b90f863..dc259b2 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -117,6 +117,7 @@ 19B665D92B4EEDDD0083E63C /* SignUpWorkerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */; }; 19B665DA2B4EEDDD0083E63C /* SignUpInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */; }; 19B665DB2B4EEDDD0083E63C /* SignUpPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */; }; + 19B665DD2B4F0A7B0083E63C /* MockSignUpWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665DC2B4F0A7B0083E63C /* MockSignUpWorker.swift */; }; 19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */; }; 19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */; }; 19E79AC02B0A85D0009EA9ED /* LoopingPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E79ABF2B0A85D0009EA9ED /* LoopingPlayerView.swift */; }; @@ -376,6 +377,7 @@ 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpWorkerTests.swift; sourceTree = ""; }; 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpInteractorTests.swift; sourceTree = ""; }; 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpPresenterTests.swift; sourceTree = ""; }; + 19B665DC2B4F0A7B0083E63C /* MockSignUpWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSignUpWorker.swift; sourceTree = ""; }; 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = ""; }; 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainStored.swift; sourceTree = ""; }; 19E79ABF2B0A85D0009EA9ED /* LoopingPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopingPlayerView.swift; sourceTree = ""; }; @@ -656,6 +658,7 @@ 1925136C2B26F84E001533FA /* MockTagPlayListWorker.swift */, 192513842B27852C001533FA /* MockUserWorker.swift */, 19AE481B2B28C53800DD4612 /* MockSettingWorker.swift */, + 19B665DC2B4F0A7B0083E63C /* MockSignUpWorker.swift */, ); path = Workers; sourceTree = ""; @@ -1600,6 +1603,7 @@ files = ( 192513852B27852C001533FA /* MockUserWorker.swift in Sources */, 192513832B277CD7001533FA /* ProfilePresenterTests.swift in Sources */, + 19B665DD2B4F0A7B0083E63C /* MockSignUpWorker.swift in Sources */, 192513812B277CD7001533FA /* ProfileInteractorTests.swift in Sources */, 194C21C42B1DEE6B00C62645 /* HomeInteractorTests.swift in Sources */, FC4E0C0F2B282AE500152596 /* UploadPostPresenterTests.swift in Sources */, diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockSignUpWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockSignUpWorker.swift new file mode 100644 index 0000000..07eb3e8 --- /dev/null +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockSignUpWorker.swift @@ -0,0 +1,85 @@ +// +// MockSignUpWorker.swift +// LayoverTests +// +// Created by 김인환 on 1/11/24. +// Copyright © 2024 CodeBomber. All rights reserved. +// + +@testable import Layover +import Foundation +import OSLog + +class MockSignUpWorker: SignUpWorkerProtocol { + + // MARK: - Properties + + private let provider: ProviderType + + // MARK: - Initializer + + init(provider: ProviderType = Provider(session: .initMockSession(), + authManager: StubAuthManager())) { + self.provider = provider + } + + func signUp(withKakao socialToken: String, username: String) async -> Bool { + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) else { + return false + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + do { + var bodyParameters = [String: String]() + bodyParameters.updateValue(socialToken, forKey: "accessToken") + bodyParameters.updateValue(username, forKey: "username") + + let endPoint = EndPoint>(path: "/oauth/signup/kakao", + method: .POST, + bodyParameters: bodyParameters) + let response = try await provider.request(with: endPoint, authenticationIfNeeded: false, retryCount: 0) + return true + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return false + } + } + + func signUp(withApple identityToken: String, username: String) async -> Bool { + guard let fileLocation: URL = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json") else { + return false + } + guard let mockData: Data = try? Data(contentsOf: fileLocation) else { + return false + } + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + do { + var bodyParameters: [String: String] = [:] + bodyParameters.updateValue(identityToken, forKey: "identityToken") + bodyParameters.updateValue(username, forKey: "username") + + let endPoint = EndPoint>(path: "/oauth/signup/apple", + method: .POST, + bodyParameters: bodyParameters) + let response = try await provider.request(with: endPoint, authenticationIfNeeded: false, retryCount: 0) + return true + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return false + } + } +} diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift index 9152372..7092743 100644 --- a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpWorkerTests.swift @@ -13,12 +13,12 @@ @testable import Layover import XCTest -class SignUpWorkerTests: XCTestCase -{ +final class SignUpWorkerTests: XCTestCase { // MARK: Subject under test var sut: SignUpWorker! - + var authManagerSpy: AuthManagerSpy! + // MARK: - Test lifecycle override func setUp() { @@ -31,20 +31,149 @@ class SignUpWorkerTests: XCTestCase } // MARK: - Test setup - + func setupSignUpWorker() { - sut = SignUpWorker() + authManagerSpy = AuthManagerSpy() + sut = SignUpWorker(provider: Provider(session: .initMockSession(), authManager: StubAuthManager()), + authManager: authManagerSpy) } - // MARK: - Test doubles + // MARK: - Test Doubles + + final class AuthManagerSpy: StubAuthManager { + var loginCalled = false + var logoutCalled = false + + override init() { + super.init() + self.accessToken = nil + self.refreshToken = nil + self.loginType = nil + self.isLoggedIn = nil + } + + override func login(accessToken: String?, refreshToken: String?, loginType: LoginType?) { + loginCalled = true + super.login(accessToken: accessToken, refreshToken: refreshToken, loginType: loginType) + } + + override func logout() { + logoutCalled = true + super.logout() + } + } // MARK: - Tests - - func testSomething() { - // Given - // When + func test_카카오_회원가입을_성공적으로_했을때_true를_반환하고_로그인_처리된다() async { + // arrange + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) else { + XCTFail("Mock json 파일 로드 실패.") + return + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + // act + let isSuccess = await sut.signUp(withKakao: "MockToken", username: "안유진") + + // assert + XCTAssertTrue(isSuccess) + XCTAssertTrue(authManagerSpy.loginCalled) + XCTAssertEqual(authManagerSpy.accessToken, "mockAccessToken") + XCTAssertEqual(authManagerSpy.refreshToken, "mockRefreshToken") + XCTAssertEqual(authManagerSpy.loginType, .kakao) + XCTAssertTrue(authManagerSpy.isLoggedIn == true) + } + + func test_카카오_회원가입을_실패했을때_false를_반환하고_로그인_처리되지_않는다() async { + // arrange + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) else { + XCTFail("Mock json 파일 로드 실패.") + return + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 400, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + // act + let isSuccess = await sut.signUp(withKakao: "MockToken", username: "안유진") + + // assert + XCTAssertFalse(isSuccess) + XCTAssertFalse(authManagerSpy.loginCalled) + XCTAssertNil(authManagerSpy.accessToken) + XCTAssertNil(authManagerSpy.refreshToken) + XCTAssertNil(authManagerSpy.loginType) + XCTAssertFalse(authManagerSpy.isLoggedIn == true) + } + + func test_애플_회원가입을_성공적으로_했을때_true를_반환하고_로그인_처리된다() async { + // arrange + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) else { + XCTFail("Mock json 파일 로드 실패.") + return + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + // act + let isSuccess = await sut.signUp(withApple: "MockToken", username: "안유진") + + // assert + XCTAssertTrue(isSuccess) + XCTAssertTrue(authManagerSpy.loginCalled) + XCTAssertEqual(authManagerSpy.accessToken, "mockAccessToken") + XCTAssertEqual(authManagerSpy.refreshToken, "mockRefreshToken") + XCTAssertEqual(authManagerSpy.loginType, .apple) + XCTAssertTrue(authManagerSpy.isLoggedIn == true) + } + + func test_애플_회원가입을_실패했을때_false를_반환하고_로그인_처리되지_않는다() async { + // arrange + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "LoginData", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) else { + XCTFail("Mock json 파일 로드 실패.") + return + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 400, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + // act + let isSuccess = await sut.signUp(withApple: "MockToken", username: "안유진") - // Then + // assert + XCTAssertFalse(isSuccess) + XCTAssertFalse(authManagerSpy.loginCalled) + XCTAssertNil(authManagerSpy.accessToken) + XCTAssertNil(authManagerSpy.refreshToken) + XCTAssertNil(authManagerSpy.loginType) + XCTAssertFalse(authManagerSpy.isLoggedIn == true) } } diff --git a/iOS/Layover/LayoverTests/Stubs/StubAuthManager.swift b/iOS/Layover/LayoverTests/Stubs/StubAuthManager.swift index 9558084..69eff83 100644 --- a/iOS/Layover/LayoverTests/Stubs/StubAuthManager.swift +++ b/iOS/Layover/LayoverTests/Stubs/StubAuthManager.swift @@ -8,13 +8,30 @@ @testable import Layover import Foundation -final class StubAuthManager: AuthManagerProtocol { +class StubAuthManager: AuthManagerProtocol { - // MARK: Properties + // MARK: - Properties var accessToken: String? = "Fake Access Token" var refreshToken: String? = "Fake Refresh Token" var isLoggedIn: Bool? = true var loginType: LoginType? = .kakao var memberID: Int? = -1 + + // MARK: - Methods + + func login(accessToken: String?, refreshToken: String?, loginType: LoginType?) { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.loginType = loginType + isLoggedIn = true + } + + func logout() { + accessToken = nil + refreshToken = nil + memberID = nil + loginType = nil + isLoggedIn = false + } } From c0ff6fb7edd84b033fe1d193f4fc682d423b7e4a Mon Sep 17 00:00:00 2001 From: loinsir Date: Thu, 11 Jan 2024 03:46:00 +0900 Subject: [PATCH 4/4] =?UTF-8?q?:fire:=20SignUpViewControllerTests=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 6 +- .../SignUp/SignUpViewControllerTests.swift | 84 ------------------- 2 files changed, 1 insertion(+), 89 deletions(-) delete mode 100644 iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index dc259b2..feccac0 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -113,7 +113,6 @@ 19AE482A2B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE48292B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift */; }; 19AE482C2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE482B2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift */; }; 19AE482E2B2A24C700DD4612 /* URL+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AE482D2B2A24C700DD4612 /* URL+.swift */; }; - 19B665D82B4EEDDD0083E63C /* SignUpViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */; }; 19B665D92B4EEDDD0083E63C /* SignUpWorkerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */; }; 19B665DA2B4EEDDD0083E63C /* SignUpInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */; }; 19B665DB2B4EEDDD0083E63C /* SignUpPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */; }; @@ -373,7 +372,6 @@ 19AE48292B2A127E00DD4612 /* HLSAssetResourceLoaderDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSAssetResourceLoaderDelegate.swift; sourceTree = ""; }; 19AE482B2B2A1A8B00DD4612 /* HLSSliceResourceLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSSliceResourceLoader.swift; sourceTree = ""; }; 19AE482D2B2A24C700DD4612 /* URL+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+.swift"; sourceTree = ""; }; - 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpViewControllerTests.swift; sourceTree = ""; }; 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpWorkerTests.swift; sourceTree = ""; }; 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpInteractorTests.swift; sourceTree = ""; }; 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpPresenterTests.swift; sourceTree = ""; }; @@ -808,10 +806,9 @@ 19B665D32B4EEDDD0083E63C /* SignUp */ = { isa = PBXGroup; children = ( - 19B665D42B4EEDDD0083E63C /* SignUpViewControllerTests.swift */, - 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */, 19B665D62B4EEDDD0083E63C /* SignUpInteractorTests.swift */, 19B665D72B4EEDDD0083E63C /* SignUpPresenterTests.swift */, + 19B665D52B4EEDDD0083E63C /* SignUpWorkerTests.swift */, ); path = SignUp; sourceTree = ""; @@ -1625,7 +1622,6 @@ 19AE48172B28C2B700DD4612 /* SettingViewControllerTests.swift in Sources */, 19B665DA2B4EEDDD0083E63C /* SignUpInteractorTests.swift in Sources */, 19B665DB2B4EEDDD0083E63C /* SignUpPresenterTests.swift in Sources */, - 19B665D82B4EEDDD0083E63C /* SignUpViewControllerTests.swift in Sources */, 194C21C32B1DEE6B00C62645 /* HomeViewControllerTests.swift in Sources */, 192513692B26F7CE001533FA /* TagPlayListInteractorTests.swift in Sources */, 19AE48232B29D03D00DD4612 /* EditProfileInteractorTests.swift in Sources */, diff --git a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift b/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift deleted file mode 100644 index 85c1685..0000000 --- a/iOS/Layover/LayoverTests/Scenes/SignUp/SignUpViewControllerTests.swift +++ /dev/null @@ -1,84 +0,0 @@ -//// -//// SignUpViewControllerTests.swift -//// Layover -//// -//// Created by 김인환 on 1/6/24. -//// Copyright (c) 2024 CodeBomber. All rights reserved. -//// -//// This file was generated by the Clean Swift Xcode Templates so -//// you can apply clean architecture to your iOS and Mac projects, -//// see http://clean-swift.com -//// -// -//@testable import Layover -//import XCTest -// -//class SignUpViewControllerTests: XCTestCase { -// // MARK: Subject under test -// -// var sut: SignUpViewController! -// var window: UIWindow! -// -// // MARK: - Test lifecycle -// -// override func setUp() { -// super.setUp() -// window = UIWindow() -// setupSignUpViewController() -// } -// -// override func tearDown() { -// window = nil -// super.tearDown() -// } -// -// // MARK: - Test setup -// -// func setupSignUpViewController() { -// let bundle = Bundle.main -// let storyboard = UIStoryboard(name: "Main", bundle: bundle) -// sut = storyboard.instantiateViewController(withIdentifier: "SignUpViewController") as! SignUpViewController -// } -// -// func loadView() { -// window.addSubview(sut.view) -// RunLoop.current.run(until: Date()) -// } -// -// // MARK: - Test doubles -// -// class SignUpBusinessLogicSpy: SignUpBusinessLogic { -// var doSomethingCalled = false -// -// func doSomething(request: SignUp.Something.Request) -// { -// doSomethingCalled = true -// } -// } -// -// // MARK: - Tests -// -// func testShouldDoSomethingWhenViewIsLoaded() { -// // Given -// let spy = SignUpBusinessLogicSpy() -// sut.interactor = spy -// -// // When -// loadView() -// -// // Then -// XCTAssertTrue(spy.doSomethingCalled, "viewDidLoad() should ask the interactor to do something") -// } -// -// func testDisplaySomething() { -// // Given -// let viewModel = SignUp.Something.ViewModel() -// -// // When -// loadView() -// sut.displaySomething(viewModel: viewModel) -// -// // Then -// //XCTAssertEqual(sut.nameTextField.text, "", "displaySomething(viewModel:) should update the name text field") -// } -//}