decorator-dependency-injection 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +13 -8
- package/README.md +125 -29
- package/index.js +158 -76
- package/package.json +1 -1
- package/test/injection.test.js +164 -7
- package/test/injectionLazy.test.js +249 -0
- package/test/mock.test.js +230 -6
- package/test/proxy.test.js +130 -0
package/test/mock.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {Factory, Inject, InjectLazy, Mock, resetMock, resetMocks, Singleton} from '../index.js'
|
|
2
2
|
|
|
3
3
|
describe('Mocking', () => {
|
|
4
4
|
@Singleton()
|
|
@@ -6,6 +6,10 @@ describe('Mocking', () => {
|
|
|
6
6
|
op() {
|
|
7
7
|
return 'original'
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
op2() {
|
|
11
|
+
return 'original2'
|
|
12
|
+
}
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
class TestInjection {
|
|
@@ -20,16 +24,42 @@ describe('Mocking', () => {
|
|
|
20
24
|
@Mock(ToBeMockedSingleton)
|
|
21
25
|
class MockedSingleton {
|
|
22
26
|
op() {
|
|
23
|
-
return '
|
|
27
|
+
return 'mocked1'
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
const result = new TestInjection()
|
|
28
|
-
expect(result.toBeMockedSingleton.op()).toBe('
|
|
32
|
+
expect(result.toBeMockedSingleton.op()).toBe('mocked1')
|
|
33
|
+
expect(result.toBeMockedSingleton.op2).toBe.undefined
|
|
29
34
|
|
|
30
35
|
resetMocks()
|
|
31
36
|
const result2 = new TestInjection()
|
|
32
37
|
expect(result2.toBeMockedSingleton.op()).toBe('original')
|
|
38
|
+
expect(result2.toBeMockedSingleton.op2()).toBe('original2')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// New tests for lazy injection with mocks (non-proxied)
|
|
42
|
+
it('should inject a lazy mock singleton', () => {
|
|
43
|
+
@Mock(ToBeMockedSingleton)
|
|
44
|
+
class MockedSingletonLazy {
|
|
45
|
+
op() {
|
|
46
|
+
return 'mocked2'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class TestInjectionLazy {
|
|
51
|
+
@InjectLazy(ToBeMockedSingleton) lazyMockedSingleton
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const instance = new TestInjectionLazy()
|
|
55
|
+
const result = instance.lazyMockedSingleton
|
|
56
|
+
expect(result.op()).toBe('mocked2')
|
|
57
|
+
expect(result.op2).toBe.undefined
|
|
58
|
+
|
|
59
|
+
resetMocks()
|
|
60
|
+
const instance2 = new TestInjectionLazy()
|
|
61
|
+
expect(instance2.lazyMockedSingleton.op()).toBe('original')
|
|
62
|
+
expect(instance2.lazyMockedSingleton.op2()).toBe('original2')
|
|
33
63
|
})
|
|
34
64
|
|
|
35
65
|
@Factory()
|
|
@@ -59,13 +89,207 @@ describe('Mocking', () => {
|
|
|
59
89
|
expect(result2.toBeMockedFactory.op()).toBe('original')
|
|
60
90
|
})
|
|
61
91
|
|
|
92
|
+
// New tests for lazy injection with mock factory
|
|
93
|
+
it('should inject a lazy mock factory', () => {
|
|
94
|
+
@Mock(ToBeMockedFactory)
|
|
95
|
+
class MockedFactoryLazy {
|
|
96
|
+
op() {
|
|
97
|
+
return 'mocked'
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
class TestInjectionFactoryLazy {
|
|
102
|
+
@InjectLazy(ToBeMockedFactory) lazyMockedFactory
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const instance = new TestInjectionFactoryLazy()
|
|
106
|
+
const result = instance.lazyMockedFactory
|
|
107
|
+
expect(result.op()).toBe('mocked')
|
|
108
|
+
|
|
109
|
+
resetMocks()
|
|
110
|
+
const instance2 = new TestInjectionFactoryLazy()
|
|
111
|
+
expect(instance2.lazyMockedFactory.op()).toBe('original')
|
|
112
|
+
})
|
|
113
|
+
|
|
62
114
|
it('should throw an error if a mock is not a singleton or factory', () => {
|
|
63
115
|
expect(() => {
|
|
64
116
|
@Mock(ToBeMockedFactory)
|
|
65
|
-
class Mocked1 {
|
|
117
|
+
class Mocked1 {
|
|
118
|
+
}
|
|
66
119
|
|
|
67
120
|
@Mock(ToBeMockedFactory)
|
|
68
|
-
class Mocked2 {
|
|
121
|
+
class Mocked2 {
|
|
122
|
+
}
|
|
69
123
|
}).toThrow('Mock already defined, reset before mocking again')
|
|
70
124
|
})
|
|
71
|
-
|
|
125
|
+
|
|
126
|
+
// Edge case: Resetting specific mocks
|
|
127
|
+
it('should reset only the specified mock', () => {
|
|
128
|
+
@Singleton()
|
|
129
|
+
class A {
|
|
130
|
+
value() {
|
|
131
|
+
return 'A'
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@Singleton()
|
|
136
|
+
class B {
|
|
137
|
+
value() {
|
|
138
|
+
return 'B'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@Mock(A)
|
|
143
|
+
class MockA {
|
|
144
|
+
value() {
|
|
145
|
+
return 'mockA'
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@Mock(B)
|
|
150
|
+
class MockB {
|
|
151
|
+
value() {
|
|
152
|
+
return 'mockB'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class Test {
|
|
157
|
+
@Inject(A) a
|
|
158
|
+
@Inject(B) b
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const t = new Test()
|
|
162
|
+
expect(t.a.value()).toBe('mockA')
|
|
163
|
+
expect(t.b.value()).toBe('mockB')
|
|
164
|
+
|
|
165
|
+
resetMock(A)
|
|
166
|
+
const t2 = new Test()
|
|
167
|
+
expect(t2.a.value()).toBe('A')
|
|
168
|
+
expect(t2.b.value()).toBe('mockB')
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it('should use the latest mock when multiple mocks are applied', () => {
|
|
172
|
+
@Singleton()
|
|
173
|
+
class Original {
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Mock(Original)
|
|
177
|
+
class Mock1 {
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
resetMock(Original)
|
|
181
|
+
|
|
182
|
+
@Mock(Original)
|
|
183
|
+
class Mock2 {
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
class Test {
|
|
187
|
+
@Inject(Original) dep
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const t = new Test()
|
|
191
|
+
expect(t.dep).toBeInstanceOf(Mock2)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('should restore the original after unmocking', () => {
|
|
195
|
+
@Singleton()
|
|
196
|
+
class Orig {
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@Mock(Orig)
|
|
200
|
+
class Mocked {
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
resetMock(Orig)
|
|
204
|
+
|
|
205
|
+
class Test {
|
|
206
|
+
@Inject(Orig) dep
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const t = new Test()
|
|
210
|
+
expect(t.dep).toBeInstanceOf(Orig)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('should inject subclass correctly', () => {
|
|
214
|
+
@Singleton()
|
|
215
|
+
class Base {
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
class Sub extends Base {
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Mock(Base)
|
|
222
|
+
class SubMock extends Sub {
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
class Test {
|
|
226
|
+
@Inject(Base) dep
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const t = new Test()
|
|
230
|
+
expect(t.dep).toBeInstanceOf(Sub)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it('should use latest mock for lazy injection', () => {
|
|
234
|
+
@Singleton()
|
|
235
|
+
class Orig {
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@Mock(Orig)
|
|
239
|
+
class Mock1 {
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
resetMock(Orig)
|
|
243
|
+
|
|
244
|
+
@Mock(Orig)
|
|
245
|
+
class Mock2 {
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
class Test {
|
|
249
|
+
@InjectLazy(Orig) dep
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const t = new Test()
|
|
253
|
+
expect(t.dep).toBeInstanceOf(Mock2)
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it('should restore original after unmocking (lazy)', () => {
|
|
257
|
+
@Singleton()
|
|
258
|
+
class Orig {
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@Mock(Orig)
|
|
262
|
+
class Mocked {
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
resetMock(Orig)
|
|
266
|
+
|
|
267
|
+
class Test {
|
|
268
|
+
@InjectLazy(Orig) dep
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const t = new Test()
|
|
272
|
+
expect(t.dep).toBeInstanceOf(Orig)
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('should inject subclass correctly (lazy)', () => {
|
|
276
|
+
@Singleton()
|
|
277
|
+
class Base {
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
class Sub extends Base {
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@Mock(Base)
|
|
284
|
+
class SubMock extends Sub {
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
class Test {
|
|
288
|
+
@InjectLazy(Base) dep
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const t = new Test()
|
|
292
|
+
expect(t.dep).toBeInstanceOf(Sub)
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {Factory, Inject, InjectLazy, Mock, resetMocks, Singleton} from '../index.js'
|
|
2
|
+
|
|
3
|
+
describe('Proxy Mocking', () => {
|
|
4
|
+
@Singleton()
|
|
5
|
+
class ToBeProxiedSingleton {
|
|
6
|
+
op() {
|
|
7
|
+
return 'original'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
op2() {
|
|
11
|
+
return 'original2'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class TestInjection {
|
|
16
|
+
@Inject(ToBeProxiedSingleton) toBeProxiedSingleton
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
resetMocks()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should inject a proxy singleton', () => {
|
|
24
|
+
@Mock(ToBeProxiedSingleton, true)
|
|
25
|
+
class ProxiedSingleton {
|
|
26
|
+
op() {
|
|
27
|
+
return 'mocked'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const result = new TestInjection()
|
|
32
|
+
expect(result.toBeProxiedSingleton.op()).toBe('mocked')
|
|
33
|
+
expect(result.toBeProxiedSingleton.op2()).toBe('original2')
|
|
34
|
+
|
|
35
|
+
resetMocks()
|
|
36
|
+
const result2 = new TestInjection()
|
|
37
|
+
expect(result2.toBeProxiedSingleton.op()).toBe('original')
|
|
38
|
+
expect(result2.toBeProxiedSingleton.op2()).toBe('original2')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
@Factory()
|
|
42
|
+
class ToBeProxiedFactory {
|
|
43
|
+
op() {
|
|
44
|
+
return 'original'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
op2() {
|
|
48
|
+
return 'original2'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class TestInjectionFactory {
|
|
53
|
+
@Inject(ToBeProxiedFactory) toBeProxiedFactory
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
it('should inject a proxy factory', () => {
|
|
57
|
+
@Mock(ToBeProxiedFactory, true)
|
|
58
|
+
class ProxiedFactory {
|
|
59
|
+
op() {
|
|
60
|
+
return 'mocked'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = new TestInjectionFactory()
|
|
65
|
+
expect(result.toBeProxiedFactory.op()).toBe('mocked')
|
|
66
|
+
expect(result.toBeProxiedFactory.op2()).toBe('original2')
|
|
67
|
+
|
|
68
|
+
resetMocks()
|
|
69
|
+
const result2 = new TestInjectionFactory()
|
|
70
|
+
expect(result2.toBeProxiedFactory.op()).toBe('original')
|
|
71
|
+
expect(result2.toBeProxiedFactory.op2()).toBe('original2')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('should inject a lazy proxy singleton', () => {
|
|
75
|
+
@Mock(ToBeProxiedSingleton, true)
|
|
76
|
+
class ProxiedSingletonLazy {
|
|
77
|
+
op() {
|
|
78
|
+
return 'mocked'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class TestInjectionLazy {
|
|
83
|
+
@InjectLazy(ToBeProxiedSingleton) lazyProxiedSingleton
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const instance = new TestInjectionLazy()
|
|
87
|
+
const result = instance.lazyProxiedSingleton
|
|
88
|
+
expect(result.op()).toBe('mocked')
|
|
89
|
+
expect(result.op2()).toBe('original2')
|
|
90
|
+
|
|
91
|
+
resetMocks()
|
|
92
|
+
const instance2 = new TestInjectionLazy()
|
|
93
|
+
expect(instance2.lazyProxiedSingleton.op()).toBe('original')
|
|
94
|
+
expect(instance2.lazyProxiedSingleton.op2()).toBe('original2')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should inject a lazy proxy factory', () => {
|
|
98
|
+
@Factory()
|
|
99
|
+
class ToBeProxiedFactoryLazy {
|
|
100
|
+
op() {
|
|
101
|
+
return 'original'
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
op2() {
|
|
105
|
+
return 'original2'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class TestInjectionFactoryLazy {
|
|
110
|
+
@InjectLazy(ToBeProxiedFactoryLazy) lazyProxiedFactory
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@Mock(ToBeProxiedFactoryLazy, true)
|
|
114
|
+
class ProxiedFactoryLazy {
|
|
115
|
+
op() {
|
|
116
|
+
return 'mocked'
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const instance = new TestInjectionFactoryLazy()
|
|
121
|
+
const result = instance.lazyProxiedFactory
|
|
122
|
+
expect(result.op()).toBe('mocked')
|
|
123
|
+
expect(result.op2()).toBe('original2')
|
|
124
|
+
|
|
125
|
+
resetMocks()
|
|
126
|
+
const instance2 = new TestInjectionFactoryLazy()
|
|
127
|
+
expect(instance2.lazyProxiedFactory.op()).toBe('original')
|
|
128
|
+
expect(instance2.lazyProxiedFactory.op2()).toBe('original2')
|
|
129
|
+
})
|
|
130
|
+
})
|