From 8d18cdf0b742ab4c05c8cebede5f41b922f8cd04 Mon Sep 17 00:00:00 2001 From: Liyang Wang Date: Mon, 27 Nov 2023 17:32:54 -0500 Subject: [PATCH] unit test for friends+network mock --- .../newHere.xcodeproj/project.pbxproj | 8 ++ .../newHereTests_v2/friendsTest.swift | 90 +++++++++++++++++++ .../newHereTests_v2/mockNetworkHandler.swift | 56 ++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 app/newHere1/newHereTests_v2/friendsTest.swift create mode 100644 app/newHere1/newHereTests_v2/mockNetworkHandler.swift diff --git a/app/newHere1/newHere.xcodeproj/project.pbxproj b/app/newHere1/newHere.xcodeproj/project.pbxproj index 34194cc..533c010 100644 --- a/app/newHere1/newHere.xcodeproj/project.pbxproj +++ b/app/newHere1/newHere.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ FE69C3002B152F3C000483D4 /* messagesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE69C2FF2B152F3C000483D4 /* messagesTest.swift */; }; FE69C3082B15474D000483D4 /* profileTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE69C3062B15473D000483D4 /* profileTest.swift */; }; FE69C30B2B1549D0000483D4 /* postTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE69C3092B1549D0000483D4 /* postTest.swift */; }; + FE69C30D2B154F0D000483D4 /* friendsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE69C30C2B154F0D000483D4 /* friendsTest.swift */; }; + FE69C3102B154F82000483D4 /* mockNetworkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE69C30E2B154F7F000483D4 /* mockNetworkHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -86,6 +88,8 @@ FE69C2FF2B152F3C000483D4 /* messagesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = messagesTest.swift; sourceTree = ""; }; FE69C3062B15473D000483D4 /* profileTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = profileTest.swift; sourceTree = ""; }; FE69C3092B1549D0000483D4 /* postTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = postTest.swift; sourceTree = ""; }; + FE69C30C2B154F0D000483D4 /* friendsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = friendsTest.swift; sourceTree = ""; }; + FE69C30E2B154F7F000483D4 /* mockNetworkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = mockNetworkHandler.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -199,6 +203,8 @@ FE69C3092B1549D0000483D4 /* postTest.swift */, FE69C3062B15473D000483D4 /* profileTest.swift */, FE69C2FF2B152F3C000483D4 /* messagesTest.swift */, + FE69C30C2B154F0D000483D4 /* friendsTest.swift */, + FE69C30E2B154F7F000483D4 /* mockNetworkHandler.swift */, ); path = newHereTests_v2; sourceTree = ""; @@ -404,7 +410,9 @@ files = ( FE69C3002B152F3C000483D4 /* messagesTest.swift in Sources */, FE69C30B2B1549D0000483D4 /* postTest.swift in Sources */, + FE69C3102B154F82000483D4 /* mockNetworkHandler.swift in Sources */, FE69C3082B15474D000483D4 /* profileTest.swift in Sources */, + FE69C30D2B154F0D000483D4 /* friendsTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/app/newHere1/newHereTests_v2/friendsTest.swift b/app/newHere1/newHereTests_v2/friendsTest.swift new file mode 100644 index 0000000..bbe4769 --- /dev/null +++ b/app/newHere1/newHereTests_v2/friendsTest.swift @@ -0,0 +1,90 @@ +// +// friendsTest.swift +// newHereTests_v2 +// +// Created by Liyang Wang on 11/10/23. +// + +import XCTest +@testable import newHere + +class FriendsTests: XCTestCase { + private var isPresented: Bool! + private var friendsView: Friends! + private var mockNetworkHandler: MockNetworkHandler! + + override func setUpWithError() throws { + isPresented = true + mockNetworkHandler = MockNetworkHandler() + friendsView = Friends(isPresented: .constant(isPresented)) + friendsView.networkHandler = mockNetworkHandler + } + override func tearDownWithError() throws { + isPresented = nil + friendsView = nil + mockNetworkHandler = nil + } + + func testInitialState() { + XCTAssertTrue(friendsView.friendsList.isEmpty, "Friends list should be empty initially") + XCTAssertNil(friendsView.errorMessage, "Error message should be nil initially") + } + func testFetchFriendsOnAppear() { + mockNetworkHandler.mockGetAllUserFriendsSuccess(friends: ["Alice", "Bob"]) + friendsView.onAppear() + XCTAssertEqual(friendsView.friendsList, ["Alice", "Bob"], "Friends list should be updated after fetching friends") + } + func testDeleteFriendSuccess() { + let friendToDelete = "Alice" + friendsView.friendsList = ["Alice", "Bob"] + + mockNetworkHandler.mockDeleteFriendSuccess() + friendsView.deleteFriendByName(userId: "TestUserID", friendName: friendToDelete) { _ in } + + XCTAssertFalse(friendsView.friendsList.contains(friendToDelete), "Friend should be removed from the list upon successful deletion") + } + + func testDeleteFriendFailure() { + let friendToDelete = "Alice" + let expectedError = "Network Error" + friendsView.friendsList = ["Alice", "Bob"] + + mockNetworkHandler.mockDeleteFriendFailure(error: expectedError) + friendsView.deleteFriendByName(userId: "TestUserID", friendName: friendToDelete) { result in + if case .failure(let error) = result { + XCTAssertEqual(friendsView.errorMessage, error.localizedDescription, "Error message should be updated upon deletion failure") + } else { + XCTFail("Deletion should fail and result in an error") + } + } + } + func testDeleteNonExistingFriend() { + let nonExistingFriend = "Charlie" + friendsView.friendsList = ["Alice", "Bob"] + + mockNetworkHandler.mockDeleteFriendSuccess() + friendsView.deleteFriendByName(userId: "TestUserID", friendName: nonExistingFriend) { _ in } + + XCTAssertEqual(friendsView.friendsList, ["Alice", "Bob"], "Friends list should remain unchanged when attempting to delete a non-existing friend") + } + func testFetchFriendsFailure() { + let expectedError = "Network Error" + mockNetworkHandler.mockGetAllUserFriendsFailure(error: expectedError) + friendsView.onAppear() + XCTAssertEqual(friendsView.errorMessage, expectedError, "Error message should be updated after a failed fetch") + } + func testAddFriendSuccess() { + let newFriend = "Charlie" + mockNetworkHandler.mockAddFriendSuccess() + friendsView.searchText = newFriend + friendsView.addFriend() + XCTAssertTrue(friendsView.friendsList.contains(newFriend), "New friend should be added to the friends list") + } + func testAddFriendFailure() { + let expectedError = "Add Friend Failed" + mockNetworkHandler.mockAddFriendFailure(error: expectedError) + friendsView.addFriend() + XCTAssertEqual(friendsView.errorMessage, expectedError, "Error message should be updated after a failed add friend attempt") + } + +} diff --git a/app/newHere1/newHereTests_v2/mockNetworkHandler.swift b/app/newHere1/newHereTests_v2/mockNetworkHandler.swift new file mode 100644 index 0000000..88777f3 --- /dev/null +++ b/app/newHere1/newHereTests_v2/mockNetworkHandler.swift @@ -0,0 +1,56 @@ +// +// mockNetworkHandler.swift +// newHere +// +// Created by Liyang Wang on 11/10/23. +// + +import Foundation + +class MockNetworkHandler { + var friendsList: [String] = [] + var addFriendResult: Result? + var deleteFriendResult: Result? + var getAllFriendsResult: Result<[String], Error>? + + init() { + } + func mockAddFriendSuccess() { + addFriendResult = .success(()) + } + func mockAddFriendFailure(error: String) { + addFriendResult = .failure(MockError(errorDescription: error)) + } + func mockDeleteFriendSuccess() { + deleteFriendResult = .success(()) + } + func mockDeleteFriendFailure(error: String) { + deleteFriendResult = .failure(MockError(errorDescription: error)) + } + func mockGetAllUserFriendsSuccess(friends: [String]) { + getAllFriendsResult = .success(friends) + } + func mockGetAllUserFriendsFailure(error: String) { + getAllFriendsResult = .failure(MockError(errorDescription: error)) + } + + func addFriendByName(userId: String, friendName: String, completion: (Result) -> Void) { + if let result = addFriendResult { + completion(result) + } + } + func deleteFriendByName(userId: String, friendName: String, completion: (Result) -> Void) { + if let result = deleteFriendResult { + completion(result) + } + } + func getAllUserFriends(userId: String, completion: (Result<[String], Error>) -> Void) { + if let result = getAllFriendsResult { + completion(result) + } + } + + struct MockError: Error { + var errorDescription: String? + } +}