Skip to content

Commit 7756ea8

Browse files
authored
Merge pull request #23 from strvcom/feat/swift-testing
Feat: Swift Testing framework (2/3)
2 parents 10d1769 + f933365 commit 7756ea8

22 files changed

Lines changed: 951 additions & 678 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ __Sections__
1717

1818
- Support for multiple arguments. Code clean up.
1919
- Using parameter packs for multiple arguments
20+
- Tests are converted to the new Swift Testing framework
2021

2122
## [1.0.4]
2223

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ container.register { container in
100100
In the factory closure, we typically just call the dependency initializer and we resolve its input parameters from the container. You can get rid of this duplicated boiler-plate by using `autoregister` method where you specify just the initializer that should be used to initialize the dependency, instead of writing the same factories over and over again. The above example then looks like this:
101101
```swift
102102
let container = Container()
103-
container.autoregister(initializer: Dependency.init)
103+
container.autoregister(in: .shared, initializer: Dependency.init)
104104
```
105105
Similarly, we can use autoregistration with an argument and replace this:
106106
```swift
@@ -166,7 +166,7 @@ class Singletons {
166166
static let container = Container()
167167

168168
static func configure() {
169-
container.autoregister(initializer: Dependency.init)
169+
container.autoregister(in: .shared, initializer: Dependency.init)
170170
}
171171
}
172172

@@ -183,7 +183,7 @@ class Object {
183183
When using the `@Injected` property wrapper, the dependency is resolved right in the moment when the property is instantiated. If you prefer to resolve the dependency only when it is accessed for the first time, you should rather use `@LazyInjected`:
184184
```swift
185185
let container = Container()
186-
container.autoregister(initializer: Dependency.init)
186+
container.autoregister(in: .shared, initializer: Dependency.init)
187187

188188
class Object {
189189
@LazyInjected(from: container) var dependency: Dependency

Sources/Container/Async/AsyncContainer.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ public actor AsyncContainer: AsyncDependencyResolving, AsyncDependencyRegisterin
9999
public func tryResolve<Dependency: Sendable, each Argument: Sendable>(type: Dependency.Type, arguments: repeat each Argument) async throws -> Dependency {
100100
let identifier = RegistrationIdentifier(type: type, argumentTypes: repeat (each Argument).self)
101101

102+
if identifier.argumentCount > RegistrationIdentifierConstant.maximumArgumentCount {
103+
throw ResolutionError.tooManyArguments(
104+
message: "Maximum number of arguments is \(RegistrationIdentifierConstant.maximumArgumentCount). Got \(identifier.argumentCount)."
105+
)
106+
}
107+
102108
let registration = try getRegistration(with: identifier)
103109

104110
// Pack arguments into a tuple for storage - this matches how AsyncRegistration expects them

Sources/Container/Sync/Container.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ open class Container: DependencyAutoregistering, DependencyResolving, Dependency
9595
open func tryResolve<Dependency, each Argument>(type: Dependency.Type, arguments: repeat each Argument) throws -> Dependency {
9696
let identifier = RegistrationIdentifier(type: type, argumentTypes: repeat (each Argument).self)
9797

98+
if identifier.argumentCount > RegistrationIdentifierConstant.maximumArgumentCount {
99+
throw ResolutionError.tooManyArguments(
100+
message: "Maximum number of arguments is \(RegistrationIdentifierConstant.maximumArgumentCount). Got \(identifier.argumentCount)."
101+
)
102+
}
103+
98104
let registration = try getRegistration(with: identifier)
99105

100106
// Pack arguments into a tuple for storage - this matches how Registration expects them

Sources/Models/RegistrationIdentifier.swift

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
import Foundation
99

10-
/// Maximum number of arguments supported for dependency resolution
11-
private enum Constant {
10+
/// Maximum number of arguments supported for dependency resolution (enforced at resolve time)
11+
enum RegistrationIdentifierConstant {
1212
static let maximumArgumentCount = 3
1313
}
1414

@@ -17,7 +17,11 @@ struct RegistrationIdentifier: Sendable {
1717
let typeIdentifier: ObjectIdentifier
1818
let argumentIdentifiers: [ObjectIdentifier]
1919

20-
/// Initializer using parameter packs for any number of argument types
20+
/// Number of argument types (used to enforce maximum at resolve time)
21+
var argumentCount: Int { argumentIdentifiers.count }
22+
23+
/// Initializer using parameter packs for any number of argument types.
24+
/// Registration with more than 3 arguments is allowed; resolution with more than 3 arguments will throw.
2125
///
2226
/// - Parameters:
2327
/// - type: Type of the dependency
@@ -28,11 +32,6 @@ struct RegistrationIdentifier: Sendable {
2832
var identifiers: [ObjectIdentifier] = []
2933
repeat identifiers.append(ObjectIdentifier((each Argument).self))
3034

31-
precondition(
32-
identifiers.count <= Constant.maximumArgumentCount,
33-
"Maximum number of arguments is \(Constant.maximumArgumentCount). Got \(identifiers.count)."
34-
)
35-
3635
argumentIdentifiers = identifiers
3736
}
3837

Sources/Models/ResolutionError.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ public enum ResolutionError: Error {
1515
/// The dependency with the required type is registered within the container but the factory closure expects a different argument type
1616
case unmatchingArgumentType(message: String)
1717

18+
/// More than the maximum supported number of arguments (3) was passed to resolve
19+
case tooManyArguments(message: String)
20+
1821
public var localizedDescription: String {
1922
switch self {
2023
case let .dependencyNotRegistered(message):
2124
return "Dependency not registered: \(message)"
2225
case let .unmatchingArgumentType(message):
2326
return "Unmatching argument type: \(message)"
27+
case let .tooManyArguments(message):
28+
return "Too many arguments: \(message)"
2429
}
2530
}
2631
}

Sources/Protocols/Registration/Async/AsyncDependencyRegistering.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,6 @@ public protocol AsyncDependencyRegistering {
3838

3939
// MARK: Overloaded factory methods
4040
public extension AsyncDependencyRegistering {
41-
/// Default ``DependencyScope`` value
42-
///
43-
/// The default value is `shared`
44-
static var defaultScope: DependencyScope {
45-
DependencyScope.shared
46-
}
47-
4841
/// Register a dependency with an implicit type determined by the factory closure return type
4942
///
5043
/// - Parameters:

Sources/Protocols/Registration/Sync/DependencyAutoregistering.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ public extension DependencyAutoregistering {
148148
///
149149
/// - Parameters:
150150
/// - type: Type of the dependency to register. Default value is implicitly inferred from the initializer return type
151-
/// - scope: Scope of the dependency. If `.new` is used, the initializer is called on each `resolve` call. If `.shared` is used, the initializer is called only the first time, the instance is cached and it is returned for all subsequent `resolve` calls, i.e. it is a singleton. The default value is `.shared`
151+
/// - scope: Scope of the dependency. If `.new` is used, the initializer is called on each `resolve` call. If `.shared` is used, the initializer is called only the first time, the instance is cached and it is returned for all subsequent `resolve` calls, i.e. it is a singleton
152152
/// - initializer: Initializer method of the `Dependency` that should be used to instantiate the dependency when it is being resolved from the container
153153
func autoregister<Dependency, each Parameter>(
154154
type: Dependency.Type = Dependency.self,
155-
in scope: DependencyScope = Self.defaultScope,
155+
in scope: DependencyScope,
156156
initializer: @escaping (repeat each Parameter) -> Dependency
157157
) {
158158
let factory: Factory<Dependency> = { resolver in

Sources/Protocols/Registration/Sync/DependencyRegistering.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,6 @@ public protocol DependencyRegistering {
3838

3939
// MARK: Overloaded factory methods
4040
public extension DependencyRegistering {
41-
/// Default ``DependencyScope`` value
42-
///
43-
/// The default value is `shared`
44-
static var defaultScope: DependencyScope {
45-
DependencyScope.shared
46-
}
47-
4841
/// Register a dependency with an implicit type determined by the factory closure return type
4942
///
5043
/// - Parameters:

Tests/Common/Async/AsyncDITestCase.swift

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)