[TDD] AuthManager
When Sign-in Service Is Not Decided
2 min readFeb 6, 2025
Instead of writing logic directly inside AuthManager
, we abstract it using AuthServiceProtocol
.
protocol AuthServiceProtocol {
func signIn(completion: @escaping (Bool) -> Void)
func signOut()
}
class AuthManager {
private let authService: AuthServiceProtocol
init(authService: AuthServiceProtocol) {
self.authService = authService
}
func signIn(callback: @escaping (Bool) -> Void) {
authService.signIn { success in
callback(success)
}
}
func signOut() {
authService.signOut()
}
}
AuthManager
now works independently of Google/Facebook.- We can inject a mock service for testing.
- The real sign-in logic can be implemented later.
Since we don’t have Google/Facebook auth yet, we create a mock service that simulates login/logout behavior.
class MockAuthService: AuthServiceProtocol {
var isSignInSuccessful = true
func signIn(completion: @escaping (Bool) -> Void) {
completion(isSignInSuccessful) // Simulates login result
}
func signOut() {
print("User signed out")
}
}
- We avoid calling real authentication APIs in tests.
- We can control the sign-in success/failure behavior.
Now, we can test AuthManager
using XCTest.
import XCTest
class AuthManagerTests: XCTestCase {
var authManager: AuthManager!
var mockAuthService: MockAuthService!
override func setUp() {
super.setUp()
mockAuthService = MockAuthService()
authManager = AuthManager(authService: mockAuthService)
}
func testSignInSuccess() {
mockAuthService.isSignInSuccessful = true
let expectation = self.expectation(description: "Sign-in should succeed")
authManager.signIn { success in
XCTAssertTrue(success, "Expected sign-in to be successful")
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)
}
func testSignInFailure() {
mockAuthService.isSignInSuccessful = false
let expectation = self.expectation(description: "Sign-in should fail")
authManager.signIn { success in
XCTAssertFalse(success, "Expected sign-in to fail")
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)
}
func testSignOut() {
// No need for an async expectation since signOut() is synchronous
authManager.signOut()
XCTAssert(true, "Sign-out function executed successfully")
}
}
testSignInSuccess
→ Simulates a successful login.testSignInFailure
→ Simulates a failed login.testSignOut
→ EnsuressignOut()
runs without errors.