diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 559a7502..d3b14bec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: strategy: matrix: swift: - - '6.0' + - '6.2' name: Ubuntu (Swift ${{ matrix.swift }}) runs-on: ubuntu-latest container: swift:${{ matrix.swift }} diff --git a/Sources/DependenciesTestSupport/TestTrait.swift b/Sources/DependenciesTestSupport/TestTrait.swift index dc40e15c..8d083154 100644 --- a/Sources/DependenciesTestSupport/TestTrait.swift +++ b/Sources/DependenciesTestSupport/TestTrait.swift @@ -7,6 +7,7 @@ @_documentation(visibility: private) public struct _DependenciesTrait: TestScoping, TestTrait, SuiteTrait { let updateValues: @Sendable (inout DependencyValues) async throws -> Void + var tearDown: @Sendable (DependencyValues) async throws -> Void = { _ in } @TaskLocal static var isRoot = true @@ -24,6 +25,7 @@ } operation: { try await Self.$isRoot.withValue(false) { try await function() + try await tearDown(DependencyValues._current) } } } @@ -122,10 +124,26 @@ /// } /// ``` /// + /// An additional trailing closure can be provided that is executed after the test finishes + /// allow cleanup, such as closing resources: + /// + /// ```swift + /// @Test( + /// .dependencies { + /// $0.defaultDatabase = Database() + /// } tearDown: { + /// $0.defaultDatabase.close() + /// } + /// ) + /// func feature() { + /// // ... + /// } + /// ``` public static func dependencies( - _ updateValues: @escaping @Sendable (inout DependencyValues) async throws -> Void + _ updateValues: @escaping @Sendable (inout DependencyValues) async throws -> Void, + tearDown: @escaping @Sendable (DependencyValues) async throws -> Void = { _ in } ) -> Self { - Self(updateValues: updateValues) + Self(updateValues: updateValues, tearDown: tearDown) } } #else diff --git a/Tests/DependenciesTests/TestTraitTests.swift b/Tests/DependenciesTests/TestTraitTests.swift index 2e759122..f888c100 100644 --- a/Tests/DependenciesTests/TestTraitTests.swift +++ b/Tests/DependenciesTests/TestTraitTests.swift @@ -31,5 +31,27 @@ try await Task.sleep(for: .milliseconds(1)) } } + + @Test( + .dependencies { + $0[TearDownDependency.self] = TearDownDependency() + } tearDown: { + $0[TearDownDependency.self].tearDown() + } + ) func tearDown() { + } + } + +final class TearDownDependency: @unchecked Sendable, TestDependencyKey { + var didExplicitlyTearDown = false + func tearDown() { + didExplicitlyTearDown = true + } + deinit { + #expect(didExplicitlyTearDown, "Did not explicitly tear down.") + } + static var testValue: TearDownDependency { + TearDownDependency() } +} #endif