[TDD] Integrating AuthManager
and SessionManager
2 min readFeb 6, 2025
Since we are following a dependency injection pattern, both AuthManager
and SessionManager
will depend on a storage solution for user data persistence (e.g., SessionStorage
).
Refactored AuthManager
protocol AuthServiceProtocol {
func signIn(completion: @escaping (User?) -> Void)
func signOut()
}
class AuthManager {
private let authService: AuthServiceProtocol
private let sessionManager: SessionManager
init(
authService: AuthServiceProtocol,
sessionManager: SessionManager
) {
self.authService = authService
self.sessionManager = sessionManager
}
func signIn(callback: @escaping (User?) -> Void) {
authService.signIn { [weak self] user in
if let user = user {
self?.sessionManager.saveUser(user)
}
callback(user)
}
}
func signOut() {
authService.signOut()
}
}
Now that AuthManager
and SessionManager
are integrated, you can write tests for this flow to make sure sign-in and sign-out behavior works as expected.
class AuthManagerTests: XCTestCase {
var authManager: AuthManager!
var mockAuthService: MockAuthService!
var mockStorage: MockStorage!
override func setUp() {
super.setUp()
mockStorage = MockStorage()
let sessionManager = SessionManager(storage: mockStorage)
mockAuthService = MockAuthService()
authManager = AuthManager(
authService: mockAuthService,
sessionManager: sessionManager)
}
func testSignInSuccess() {
mockAuthService.user = User(id: 123, name: "John Doe", email: "john@example.com")
let expectation = self.expectation(description: "Sign in should succeed")
authManager.signIn { user in
XCTAssertNotNil(user, "User should be not nil")
XCTAssertNotNil(self.mockStorage.storageUser, "User should be saved to session")
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)
}
func testSignInFailure() {
mockAuthService.user = nil
let expectation = self.expectation(description: "Sign in should fail")
authManager.signIn { user in
XCTAssertNil(user, "Expected sign-in to be fail")
expectation.fulfill()
}
wait(for: [expectation], timeout: 1.0)
}
func testSignOut() {
authManager.signOut()
XCTAssert(true, "Sign-out function executed succesfully")
}
}
AuthManager
handles authentication logic and relies onSessionManager
to persist the user session.SessionManager
abstracts the session persistence mechanism, allowing you to easily swap storage (e.g.,UserDefaults
,Keychain
) later.- Unit tests ensure correctness by mocking both authentication and session storage behavior, so no real API calls or storage operations are made during tests.