Does providing testValue mean you don't need to explicitly override dependency in tests? #93
-
I was going through the documentation and came across this: withDependencies {
$0.context = .test
} operation: {
// Dependencies accessed here default to their "test" value
} Does this mean if I provide a class SomeClass: FirstProtocol { /* ... */ }
enum FirstDependencyKey: DependencyKey {
static let liveValue: any FirstProtocol = SomeClass()
}
extension DependencyValues {
var apiClientOne: FirstProtocol {
get { self[FirstDependencyKey.self] }
set { self[FirstDependencyKey.self] = newValue }
}
}
class SomeViewModel: ObservableObject {
@Published var isAwesome: Bool = false
@Dependency(\.apiClientOne) var apiClientOne
func onButtonTapped() {
apiClientOne.fetchUser {
isAwesome = true
}
}
}
// Inside unit test target
extension FirstDependencyKey {
static let testValue: any FirstProtocol = /* ... */
}
func test_someAction_in_someClass() {
// Given
let sut = withDependencies {
$0.context = .test
} operation: {
SomeViewModel()
}
// When
sut.onButtonTapped()
// Then
XCTAssertTrue(sut.isAwesome)
} In example like above. I keep getting error like: test_someAction_in_someClass(): @Dependency(\. apiClientOne) has no test implementation, but was accessed from a test context: I'm not sure what I'm doing incorrect. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
Hey @Muhammed9991! |
Beta Was this translation helpful? Give feedback.
This is a gotcha: you need to define all the requirements in the same module in your case. You can conform to
TestDependencyKey
and then later toDependencyKey
in a parent module, but once you conform toDependencyKey
, all the values are set and the ones that you declared in the tests are not considered as fulfillments of the protocol.