Created
November 17, 2015 13:40
-
-
Save eofster/e988ac34d4b4670d576f to your computer and use it in GitHub Desktop.
Dependency injection example with tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import XCTest | |
////////////////////////////////////////////////////////////////////// | |
// Preferences | |
protocol UserDefaults { | |
func stringForKey(key: String) -> String | |
} | |
class Preferences { | |
let userDefaults: UserDefaults | |
init(userDefaults: UserDefaults) { | |
self.userDefaults = userDefaults | |
} | |
var username: String { | |
return userDefaults.stringForKey("Username") | |
} | |
} | |
class PreferencesTests: XCTestCase { | |
func testGetsUsernameFromUserDefaults() { | |
let userDefaultsSpy = UserDefaultsSpy() | |
userDefaultsSpy.stringForKeyResult = "john" | |
let preferences = Preferences(userDefaults: userDefaultsSpy) | |
let username = preferences.username | |
XCTAssertTrue(userDefaultsSpy.didCallStringForKey) | |
XCTAssertEqual(userDefaultsSpy.keyPassedToStringForKey, "Username") | |
XCTAssertEqual(username, "john") | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Preferences logger | |
protocol LogOutput { | |
func logMessage(message: String) | |
} | |
class PreferencesLogger { | |
let preferences: Preferences | |
let output: LogOutput | |
init(preferences: Preferences, output: LogOutput) { | |
self.preferences = preferences | |
self.output = output | |
} | |
func log() { | |
output.logMessage("Username: \(preferences.username)") | |
} | |
} | |
class PreferencesLoggerTests: XCTestCase { | |
func testLogsUsername() { | |
let userDefaultsStub = UserDefaultsSpy() | |
userDefaultsStub.stringForKeyResult = "john" | |
let preferences = Preferences(userDefaults: userDefaultsStub) | |
let logOutputSpy = LogOutputSpy() | |
let preferencesLogger = PreferencesLogger(preferences: preferences, output: logOutputSpy) | |
preferencesLogger.log() | |
XCTAssertEqual(logOutputSpy.loggedMessage, "Username: john") | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Test doubles | |
class UserDefaultsSpy: UserDefaults { | |
var stringForKeyResult = "" | |
private(set) var didCallStringForKey = false | |
private(set) var keyPassedToStringForKey = "" | |
func stringForKey(key: String) -> String { | |
didCallStringForKey = true | |
keyPassedToStringForKey = key | |
return stringForKeyResult | |
} | |
} | |
class LogOutputSpy: LogOutput { | |
private(set) var loggedMessage = "" | |
func logMessage(message: String) { | |
loggedMessage = message | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// UserDefaults implementation | |
class SystemUserDefaultsAdapter: UserDefaults { | |
let systemUserDefaults: NSUserDefaults | |
init(systemUserDefaults: NSUserDefaults) { | |
self.systemUserDefaults = systemUserDefaults | |
} | |
func stringForKey(key: String) -> String { | |
if let string = systemUserDefaults.stringForKey(key) { | |
return string | |
} else { | |
fatalError("Could not find string for key: \(key)") | |
} | |
} | |
} | |
// LogOutput implementation | |
class SystemConsoleOutput: LogOutput { | |
func logMessage(message: String) { | |
print(message) | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Usage | |
NSUserDefaults.standardUserDefaults().setObject("john", forKey: "Username") | |
let userDefaults = SystemUserDefaultsAdapter(systemUserDefaults: NSUserDefaults.standardUserDefaults()) | |
let preferences = Preferences(userDefaults: userDefaults) | |
let preferencesLogger = PreferencesLogger(preferences: preferences, output: SystemConsoleOutput()) | |
preferencesLogger.log() | |
NSUserDefaults.standardUserDefaults().removeObjectForKey("Username") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment