Skip to content

Commit 06b24a9

Browse files
committed
Add unit tests for multiprovider
Signed-off-by: jescriba <joshua.escribano@includedhealth.com>
1 parent df29538 commit 06b24a9

File tree

3 files changed

+393
-2
lines changed

3 files changed

+393
-2
lines changed

Sources/OpenFeature/Provider/MultiProvider/FirstSuccessfulStrategy.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ final public class FirstSuccessfulStrategy: Strategy {
2020
}
2121
}
2222

23-
throw OpenFeatureError.generalError(
24-
message: "No provider returned a successful evaluation for the requested flag.")
23+
throw OpenFeatureError.flagNotFoundError(key: key)
2524
}
2625
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import Combine
2+
import Foundation
3+
4+
@testable import OpenFeature
5+
6+
/// A mock provider that can be used to test provider events with payloads.
7+
/// It can be configured with a set of callbacks that will be called when the provider is initialized
8+
class MockProvider: FeatureProvider {
9+
static let name = "MockProvider"
10+
var metadata: ProviderMetadata = MockProviderMetadata()
11+
12+
var hooks: [any Hook] = []
13+
var throwFatal = false
14+
private let eventHandler = EventHandler()
15+
private let _onContextSet: (EvaluationContext?, EvaluationContext) async throws -> Void
16+
private let _initialize: (EvaluationContext?) async throws -> Void
17+
private let _getBooleanEvaluation: (String, Bool, EvaluationContext?) throws -> ProviderEvaluation<Bool>
18+
private let _getStringEvaluation: (String, String, EvaluationContext?) throws -> ProviderEvaluation<String>
19+
private let _getIntegerEvaluation: (String, Int64, EvaluationContext?) throws -> ProviderEvaluation<Int64>
20+
private let _getDoubleEvaluation: (String, Double, EvaluationContext?) throws -> ProviderEvaluation<Double>
21+
private let _getObjectEvaluation: (String, Value, EvaluationContext?) throws -> ProviderEvaluation<Value>
22+
private let _observe: () -> AnyPublisher<ProviderEvent?, Never>
23+
24+
/// Initialize the provider with a set of callbacks that will be called when the provider is initialized,
25+
init(
26+
onContextSet: @escaping (EvaluationContext?, EvaluationContext) async throws -> Void = { _, _ in },
27+
initialize: @escaping (EvaluationContext?) async throws -> Void = { _ in },
28+
getBooleanEvaluation: @escaping (
29+
String,
30+
Bool,
31+
EvaluationContext?
32+
) throws -> ProviderEvaluation<Bool> = { _, fallback, _ in
33+
return ProviderEvaluation(value: fallback, flagMetadata: [:])
34+
},
35+
getStringEvaluation: @escaping (
36+
String,
37+
String,
38+
EvaluationContext?
39+
) throws -> ProviderEvaluation<String> = { _, fallback, _ in
40+
return ProviderEvaluation(value: fallback, flagMetadata: [:])
41+
},
42+
getIntegerEvaluation: @escaping (
43+
String,
44+
Int64,
45+
EvaluationContext?
46+
) throws -> ProviderEvaluation<Int64> = { _, fallback, _ in
47+
return ProviderEvaluation(value: fallback, flagMetadata: [:])
48+
},
49+
getDoubleEvaluation: @escaping (
50+
String,
51+
Double,
52+
EvaluationContext?
53+
) throws -> ProviderEvaluation<Double> = { _, fallback, _ in
54+
return ProviderEvaluation(value: fallback, flagMetadata: [:])
55+
},
56+
getObjectEvaluation: @escaping (
57+
String,
58+
Value,
59+
EvaluationContext?
60+
) throws -> ProviderEvaluation<Value> = { _, fallback, _ in
61+
return ProviderEvaluation(value: fallback, flagMetadata: [:])
62+
},
63+
observe: @escaping () -> AnyPublisher<ProviderEvent?, Never> = { Just(nil).eraseToAnyPublisher() }
64+
) {
65+
self._onContextSet = onContextSet
66+
self._initialize = initialize
67+
self._getBooleanEvaluation = getBooleanEvaluation
68+
self._getStringEvaluation = getStringEvaluation
69+
self._getIntegerEvaluation = getIntegerEvaluation
70+
self._getDoubleEvaluation = getDoubleEvaluation
71+
self._getObjectEvaluation = getObjectEvaluation
72+
self._observe = observe
73+
}
74+
75+
func onContextSet(oldContext: EvaluationContext?, newContext: EvaluationContext) async throws {
76+
try await _onContextSet(oldContext, newContext)
77+
}
78+
79+
func initialize(initialContext: EvaluationContext?) async throws {
80+
try await _initialize(initialContext)
81+
}
82+
83+
func getBooleanEvaluation(key: String, defaultValue: Bool, context: EvaluationContext?) throws
84+
-> ProviderEvaluation<Bool>
85+
{
86+
try _getBooleanEvaluation(key, defaultValue, context)
87+
}
88+
89+
func getStringEvaluation(key: String, defaultValue: String, context: EvaluationContext?) throws
90+
-> ProviderEvaluation<String>
91+
{
92+
try _getStringEvaluation(key, defaultValue, context)
93+
}
94+
95+
func getIntegerEvaluation(key: String, defaultValue: Int64, context: EvaluationContext?) throws
96+
-> ProviderEvaluation<Int64>
97+
{
98+
try _getIntegerEvaluation(key, defaultValue, context)
99+
}
100+
101+
func getDoubleEvaluation(key: String, defaultValue: Double, context: EvaluationContext?) throws
102+
-> ProviderEvaluation<Double>
103+
{
104+
try _getDoubleEvaluation(key, defaultValue, context)
105+
}
106+
107+
func getObjectEvaluation(key: String, defaultValue: Value, context: EvaluationContext?) throws
108+
-> ProviderEvaluation<Value>
109+
{
110+
try _getObjectEvaluation(key, defaultValue, context)
111+
}
112+
113+
func observe() -> AnyPublisher<ProviderEvent?, Never> {
114+
_observe()
115+
}
116+
}
117+
118+
extension MockProvider {
119+
struct MockProviderMetadata: ProviderMetadata {
120+
var name: String? = MockProvider.name
121+
}
122+
}
123+
124+
extension MockProvider {
125+
enum MockProviderError: LocalizedError {
126+
case message(String)
127+
128+
var errorDescription: String? {
129+
switch self {
130+
case .message(let message):
131+
return message
132+
}
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)