Test Double in Swift - Fake
A Fake Object offers limited functionality like the real object. But the implementation is lightweight. The fake object avoids the complications that make the real thing a difficult dependency.
- How can we verify logic independently when depended-on objects cannot be used?
- How can we avoid Slow Tests?
When you can’t use a real implementation in your test (network/database). You
should use a Fake Object
whenever our SUT
depends on other components that are
unavailable or which make testing difficult or slow.
Some situations:
- Fake Database
- In-Memory Database
- Fake Web Service
- Fake Service Layer
- “Inject a Fake Object that implements async, but does so synchronously.”
Fake Service example
protocol Service {
func hello(_ name: String) -> String
}
class Greet {
let service: Service
init(_ service: Service) {
self.service = service
}
func greeting(_ name: String) -> String {
return self.service.hello(name)
}
}
Define a Fake Object that conforms to the protocol. Inject it from test code, and use to write test cases.
struct FakeService: Service {
func hello(_ name: String) -> String {
return "Hello, \(name)"
}
}
class GreetTests: XCTestCase {
func test_greet_withWebService_shouldStartWithHello() {
let sut = Greet(FakeService())
let result = sut.greeting("Dummy")
XCTAssertTrue(result.hasPrefix("Hello"))
}
}