Skip to content

Commit 5241b79

Browse files
committed
Update README
1 parent cf36c3a commit 5241b79

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

README.md

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ One way to do this is to create an instance of the `AnalyticsClient` type that s
9595
import XCTest
9696

9797
extension AnalyticsClient {
98-
static let failing = Self(
99-
track: { _ in XCTFail("AnalyticsClient.track is unimplemented.") }
98+
static let unimplemented = Self(
99+
track: { _ in XCTFail("\(Self.self).track is unimplemented.") }
100100
)
101101
}
102102
```
@@ -106,7 +106,7 @@ With this you can write a test that proves analytics are never tracked, and even
106106
```swift
107107
func testValidation() {
108108
let viewModel = LoginViewModel(
109-
analytics: .failing
109+
analytics: .unimplemented
110110
)
111111

112112
...
@@ -115,7 +115,7 @@ func testValidation() {
115115

116116
However, you cannot ship this code with the target that defines `AnalyticsClient`. You either need to extract it out to a test support module (which means `AnalyticsClient` must also be extracted), or the code must be confined to a test target and thus not shareable.
117117

118-
However, with `XCTestDynamicOverlay` we can have our cake and eat it too 😋. We can define both the client type and the failing instance right next to each in application code without needing to extract out needless modules or targets:
118+
However, with XCTest Dynamic Overlay we can have our cake and eat it too 😋. We can define both the client type and the unimplemented instance right next to each in application code without needing to extract out needless modules or targets:
119119

120120
```swift
121121
struct AnalyticsClient {
@@ -130,12 +130,42 @@ struct AnalyticsClient {
130130
import XCTestDynamicOverlay
131131

132132
extension AnalyticsClient {
133-
static let failing = Self(
134-
track: { _ in XCTFail("AnalyticsClient.track is unimplemented.") }
133+
static let unimplemented = Self(
134+
track: { _ in XCTFail("\(Self.self).track is unimplemented.") }
135135
)
136136
}
137137
```
138138

139+
XCTest Dynamic Overlay also comes with a helper that simplifies this exact pattern: `XCTUnimplemented`. It creates failing closures for you:
140+
141+
```swift
142+
extension AnalyticsClient {
143+
static let unimplemented = Self(
144+
track: XCTUnimplemented("\(Self.self).track")
145+
)
146+
}
147+
```
148+
149+
And it can simplify the work of more complex dependency endpoints, which can throw or need to return a value:
150+
151+
```swift
152+
struct AppDependencies {
153+
var date: () -> Date = Date.init,
154+
var fetchUser: (User.ID) async throws -> User,
155+
var uuid: () -> UUID = UUID.init
156+
}
157+
158+
extension AppDependencies {
159+
static let unimplemented = Self(
160+
date: XCTUnimplemented("\(Self.self).date", placeholder: Date()),
161+
fetchUser: XCTUnimplemented("\(Self.self).fetchUser"),
162+
date: XCTUnimplemented("\(Self.self).uuid", placeholder: UUID())
163+
)
164+
}
165+
```
166+
167+
The above `placeholder` parameters can be left off, but will fatal error when the endpoint is called.
168+
139169
## License
140170

141171
This library is released under the MIT license. See [LICENSE](LICENSE) for details.

0 commit comments

Comments
 (0)