diff --git a/Sources/Dependencies/Dependency.swift b/Sources/Dependencies/Dependency.swift index 270428fa..73ca3d76 100644 --- a/Sources/Dependencies/Dependency.swift +++ b/Sources/Dependencies/Dependency.swift @@ -42,6 +42,19 @@ /// entry" concept. See the articles and for more /// information. /// +/// > Important: Do **not** use `@Dependency` with "static" properties, _e.g._: +/// > +/// > ```swift +/// > struct User { +/// > @Dependency(\.uuid) static var uuid +/// > // ... +/// > } +/// > ``` +/// > +/// > Static properties are lazily initialized in Swift, and so a static `@Dependency` will lazily +/// > capture its dependency values wherever it is first accessed, and will likely produce +/// > unexpected behavior. +/// /// For the complete list of dependency values provided by the library, see the properties of the /// ``DependencyValues`` structure. /// diff --git a/Tests/DependenciesTests/DependencyTests.swift b/Tests/DependenciesTests/DependencyTests.swift index dab87671..ed0157d2 100644 --- a/Tests/DependenciesTests/DependencyTests.swift +++ b/Tests/DependenciesTests/DependencyTests.swift @@ -182,7 +182,30 @@ final class DependencyTests: XCTestCase { XCTAssertEqual(9000, greatGrandchild.int) XCTAssertEqual("cool", greatGrandchild.string) } + + // NB: `@Dependency` should not be used as a `static var` because of the following behavior. + func testStaticDependencyCachesFirstUse() { + struct User { + @Dependency(\.uuid) static var uuid + + let id: UUID + + init() { + self.id = Self.uuid() + } + } + + let user1 = withDependencies { $0.uuid = .incrementing } operation: { + User() + } + + let user2 = User() + + XCTAssertEqual(user1.id, UUID(0)) + XCTAssertEqual(user2.id, UUID(1)) + } } + private class Model { @Dependency(\.int) var int @Dependency(\.string) var string