-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp_di_test.go
More file actions
272 lines (226 loc) · 7.12 KB
/
app_di_test.go
File metadata and controls
272 lines (226 loc) · 7.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
package forge_test
import (
"context"
"testing"
"github.com/xraph/forge"
)
// TestCoreServicesTypeBasedResolution verifies that core services can be resolved by type.
func TestCoreServicesTypeBasedResolution(t *testing.T) {
app := forge.NewApp(forge.AppConfig{
Name: "test-app",
Version: "1.0.0",
Environment: "test",
})
ctx := context.Background()
if err := app.Start(ctx); err != nil {
t.Fatalf("Failed to start app: %v", err)
}
defer app.Stop(ctx)
container := app.Container()
// Test Logger resolution by type
t.Run("Logger by type", func(t *testing.T) {
logger, err := forge.InjectType[forge.Logger](container)
if err != nil {
t.Errorf("Failed to resolve Logger by type: %v", err)
}
if logger == nil {
t.Error("Logger resolved by type is nil")
}
// Verify it's the same instance as app.Logger()
if logger != app.Logger() {
t.Error("Logger resolved by type is not the same instance as app.Logger()")
}
})
// Test ConfigManager resolution by type
t.Run("ConfigManager by type", func(t *testing.T) {
config, err := forge.InjectType[forge.ConfigManager](container)
if err != nil {
t.Errorf("Failed to resolve ConfigManager by type: %v", err)
}
if config == nil {
t.Error("ConfigManager resolved by type is nil")
}
// Verify it's the same instance as app.Config()
if config != app.Config() {
t.Error("ConfigManager resolved by type is not the same instance as app.Config()")
}
})
// Test Metrics resolution by type
t.Run("Metrics by type", func(t *testing.T) {
metrics, err := forge.InjectType[forge.Metrics](container)
if err != nil {
t.Errorf("Failed to resolve Metrics by type: %v", err)
}
if metrics == nil {
t.Error("Metrics resolved by type is nil")
}
// Verify it's the same instance as app.Metrics()
if metrics != app.Metrics() {
t.Error("Metrics resolved by type is not the same instance as app.Metrics()")
}
})
// Test HealthManager resolution by type
t.Run("HealthManager by type", func(t *testing.T) {
health, err := forge.InjectType[forge.HealthManager](container)
if err != nil {
t.Errorf("Failed to resolve HealthManager by type: %v", err)
}
if health == nil {
t.Error("HealthManager resolved by type is nil")
}
// Verify it's the same instance as app.HealthManager()
if health != app.HealthManager() {
t.Error("HealthManager resolved by type is not the same instance as app.HealthManager()")
}
})
// Test Router resolution by type
t.Run("Router by type", func(t *testing.T) {
router, err := forge.InjectType[forge.Router](container)
if err != nil {
t.Errorf("Failed to resolve Router by type: %v", err)
}
if router == nil {
t.Error("Router resolved by type is nil")
}
// Verify it's the same instance as app.Router()
if router != app.Router() {
t.Error("Router resolved by type is not the same instance as app.Router()")
}
})
}
// TestCoreServicesBackwardCompatibility verifies that key-based resolution still works.
func TestCoreServicesBackwardCompatibility(t *testing.T) {
app := forge.NewApp(forge.AppConfig{
Name: "test-app",
Version: "1.0.0",
Environment: "test",
})
ctx := context.Background()
if err := app.Start(ctx); err != nil {
t.Fatalf("Failed to start app: %v", err)
}
defer app.Stop(ctx)
container := app.Container()
// Test Logger resolution by key (old pattern)
t.Run("Logger by key", func(t *testing.T) {
logger, err := forge.GetLogger(container)
if err != nil {
t.Errorf("Failed to resolve Logger by key: %v", err)
}
if logger == nil {
t.Error("Logger resolved by key is nil")
}
})
// Test Metrics resolution by key (old pattern)
t.Run("Metrics by key", func(t *testing.T) {
metrics, err := forge.GetMetrics(container)
if err != nil {
t.Errorf("Failed to resolve Metrics by key: %v", err)
}
if metrics == nil {
t.Error("Metrics resolved by key is nil")
}
})
// Test HealthManager resolution by key (old pattern)
t.Run("HealthManager by key", func(t *testing.T) {
health, err := forge.GetHealthManager(container)
if err != nil {
t.Errorf("Failed to resolve HealthManager by key: %v", err)
}
if health == nil {
t.Error("HealthManager resolved by key is nil")
}
})
}
// TestBothPatternsResolveSameInstance verifies type-based and key-based resolve the same instance.
func TestBothPatternsResolveSameInstance(t *testing.T) {
app := forge.NewApp(forge.AppConfig{
Name: "test-app",
Version: "1.0.0",
Environment: "test",
})
ctx := context.Background()
if err := app.Start(ctx); err != nil {
t.Fatalf("Failed to start app: %v", err)
}
defer app.Stop(ctx)
container := app.Container()
t.Run("Logger - same instance", func(t *testing.T) {
loggerByType, _ := forge.InjectType[forge.Logger](container)
loggerByKey, _ := forge.GetLogger(container)
if loggerByType != loggerByKey {
t.Error("Logger resolved by type and key are different instances")
}
})
t.Run("Metrics - same instance", func(t *testing.T) {
metricsByType, _ := forge.InjectType[forge.Metrics](container)
metricsByKey, _ := forge.GetMetrics(container)
if metricsByType != metricsByKey {
t.Error("Metrics resolved by type and key are different instances")
}
})
t.Run("HealthManager - same instance", func(t *testing.T) {
healthByType, _ := forge.InjectType[forge.HealthManager](container)
healthByKey, _ := forge.GetHealthManager(container)
if healthByType != healthByKey {
t.Error("HealthManager resolved by type and key are different instances")
}
})
}
// TestExtensionConstructorInjection verifies extensions can use constructor injection.
func TestExtensionConstructorInjection(t *testing.T) {
// Service that uses constructor injection
type TestService struct {
logger forge.Logger
metrics forge.Metrics
}
// Extension that registers service with constructor injection
type TestExtension struct {
*forge.BaseExtension
}
ext := &TestExtension{
BaseExtension: forge.NewBaseExtension("test", "1.0.0", "Test extension"),
}
app := forge.NewApp(forge.AppConfig{
Name: "test-app",
Version: "1.0.0",
Environment: "test",
})
// Register extension that uses constructor injection
app.RegisterExtension(ext)
ctx := context.Background()
if err := app.Start(ctx); err != nil {
t.Fatalf("Failed to start app: %v", err)
}
defer app.Stop(ctx)
// Now register the test service via the extension
err := ext.RegisterConstructor(func(logger forge.Logger, metrics forge.Metrics) (*TestService, error) {
if logger == nil {
t.Error("Logger injected into constructor is nil")
}
if metrics == nil {
t.Error("Metrics injected into constructor is nil")
}
return &TestService{
logger: logger,
metrics: metrics,
}, nil
})
if err != nil {
t.Errorf("Failed to register constructor: %v", err)
}
// Resolve the service by type
service, err := forge.InjectType[*TestService](app.Container())
if err != nil {
t.Errorf("Failed to resolve TestService by type: %v", err)
}
if service == nil {
t.Error("TestService resolved by type is nil")
}
if service.logger == nil {
t.Error("TestService.logger is nil")
}
if service.metrics == nil {
t.Error("TestService.metrics is nil")
}
}