Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(812)

Side by Side Diff: third_party/pkg/di/test/main.dart

Issue 107003007: Adding Angular's DI package & Dart unittests which test it. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/pkg/di/test/fixed-unittest.dart ('k') | third_party/pkg/di/test_tf_gen.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 @Injectables(const [
2 ClassOne,
3 CircularA,
4 CircularB,
5 MultipleConstructors,
6 NumDependency,
7 IntDependency,
8 DoubleDependency,
9 BoolDependency,
10 StringDependency
11 ])
12 library di.tests;
13
14 import 'fixed-unittest.dart';
15 import 'package:di/di.dart';
16 import 'package:di/dynamic_injector.dart';
17 import 'package:di/static_injector.dart';
18 import 'package:di/annotations.dart';
19
20 // Generated file. Run ../test_tf_gen.sh.
21 import 'type_factories_gen.dart' as type_factories_gen;
22
23 /**
24 * Annotation used to mark classes for which static type factory must be
25 * generated. For testing purposes not all classes are marked with this
26 * annotation, some classes are included in @Injectables at the top.
27 */
28 class Injectable {
29 const Injectable();
30 }
31
32 // just some classes for testing
33 @Injectable()
34 class Engine {
35 String id = 'v8-id';
36 }
37
38 @Injectable()
39 class MockEngine implements Engine {
40 String id = 'mock-id';
41 }
42
43 @Injectable()
44 class MockEngine2 implements Engine {
45 String id = 'mock-id-2';
46 }
47
48 @Injectable()
49 class Car {
50 Engine engine;
51 Injector injector;
52
53 Car(this.engine, this.injector);
54 }
55
56 class NumDependency {
57 NumDependency(num value) {}
58 }
59
60 class IntDependency {
61 IntDependency(int value) {}
62 }
63
64 class DoubleDependency {
65 DoubleDependency(double value) {}
66 }
67
68 class StringDependency {
69 StringDependency(String value) {}
70 }
71
72 class BoolDependency {
73 BoolDependency(bool value) {}
74 }
75
76
77 class CircularA {
78 CircularA(CircularB b) {}
79 }
80
81 class CircularB {
82 CircularB(CircularA a) {}
83 }
84
85 typedef int CompareInt(int a, int b);
86
87 int compareIntAsc(int a, int b) => b.compareTo(a);
88
89 class WithTypeDefDependency {
90 CompareInt compare;
91
92 WithTypeDefDependency(CompareInt c) {
93 compare = c;
94 }
95 }
96
97 class MultipleConstructors {
98 String instantiatedVia;
99 MultipleConstructors() : instantiatedVia = 'default';
100 MultipleConstructors.named() : instantiatedVia = 'named';
101 }
102
103 class InterfaceOne {
104 }
105
106 class ClassOne implements InterfaceOne {
107 ClassOne(Log log) {
108 log.add('ClassOne');
109 }
110 }
111
112 @Injectable()
113 class Log {
114 var log = [];
115
116 add(String message) => log.add(message);
117 }
118
119 class EmulatedMockEngineFactory {
120 call(Injector i) => new MockEngine();
121 }
122
123 void main() {
124 createInjectorSpec('DynamicInjector',
125 (modules, [name]) => new DynamicInjector(modules: modules, name: name));
126
127 // Initialize generated type factories.
128 type_factories_gen.main();
129
130 createInjectorSpec('StaticInjector',
131 (modules, [name]) => new StaticInjector(modules: modules, name: name,
132 typeFactories: type_factories_gen.typeFactories));
133 }
134
135 typedef Injector InjectorFactory(List<Module> modules, [String name]);
136
137 createInjectorSpec(String injectorName, InjectorFactory injectorFactory) {
138
139 describe(injectorName, () {
140
141 it('should instantiate a type', () {
142 var injector = injectorFactory([new Module()..type(Engine)]);
143 var instance = injector.get(Engine);
144
145 expect(instance, instanceOf(Engine));
146 expect(instance.id, toEqual('v8-id'));
147 });
148
149 it('should fail if no binding is found', () {
150 var injector = injectorFactory([]);
151 expect(() {
152 injector.get(Engine);
153 }, toThrow(NoProviderError, 'No provider found for Engine! '
154 '(resolving Engine)'));
155 });
156
157
158 it('should resolve basic dependencies', () {
159 var injector = injectorFactory([new Module()..type(Car)..type(Engine)]);
160 var instance = injector.get(Car);
161
162 expect(instance, instanceOf(Car));
163 expect(instance.engine.id, toEqual('v8-id'));
164 });
165
166
167 it('should allow modules and overriding providers', () {
168 var module = new Module()..type(Engine, implementedBy: MockEngine);
169
170 // injector is immutable
171 // you can't load more modules once it's instantiated
172 // (you can create a child injector)
173 var injector = injectorFactory([module]);
174 var instance = injector.get(Engine);
175
176 expect(instance.id, toEqual('mock-id'));
177 });
178
179
180 it('should only create a single instance', () {
181 var injector = injectorFactory([new Module()..type(Engine)]);
182 var first = injector.get(Engine);
183 var second = injector.get(Engine);
184
185 expect(first, toBe(second));
186 });
187
188
189 it('should allow providing values', () {
190 var module = new Module()
191 ..value(Engine, 'str value')
192 ..value(Car, 123);
193
194 var injector = injectorFactory([module]);
195 var abcInstance = injector.get(Engine);
196 var complexInstance = injector.get(Car);
197
198 expect(abcInstance, toEqual('str value'));
199 expect(complexInstance, toEqual(123));
200 });
201
202
203 it('should allow providing factory functions', () {
204 var module = new Module()..factory(Engine, (Injector injector) {
205 return 'factory-product';
206 });
207
208 var injector = injectorFactory([module]);
209 var instance = injector.get(Engine);
210
211 expect(instance, toEqual('factory-product'));
212 });
213
214
215 it('should allow providing with emulated factory functions', () {
216 var module = new Module();
217 module.factory(Engine, new EmulatedMockEngineFactory());
218
219 var injector = injectorFactory([module]);
220 var instance = injector.get(Engine);
221
222 expect(instance, new isInstanceOf<MockEngine>());
223 });
224
225
226 it('should inject injector into factory function', () {
227 var module = new Module()
228 ..type(Engine)
229 ..factory(Car, (Injector injector) {
230 return new Car(injector.get(Engine), injector);
231 });
232
233 var injector = injectorFactory([module]);
234 var instance = injector.get(Car);
235
236 expect(instance, instanceOf(Car));
237 expect(instance.engine.id, toEqual('v8-id'));
238 });
239
240
241 it('should throw an exception when injecting a primitive type', () {
242 var injector = injectorFactory([
243 new Module()
244 ..type(NumDependency)
245 ..type(IntDependency)
246 ..type(DoubleDependency)
247 ..type(BoolDependency)
248 ..type(StringDependency)
249 ]);
250
251 expect(() {
252 injector.get(NumDependency);
253 }, toThrow(NoProviderError, 'Cannot inject a primitive type of num! '
254 '(resolving NumDependency -> num)'));
255
256 expect(() {
257 injector.get(IntDependency);
258 }, toThrow(NoProviderError, 'Cannot inject a primitive type of int! '
259 '(resolving IntDependency -> int)'));
260
261 expect(() {
262 injector.get(DoubleDependency);
263 }, toThrow(NoProviderError, 'Cannot inject a primitive type of double! '
264 '(resolving DoubleDependency -> double)'));
265
266 expect(() {
267 injector.get(BoolDependency);
268 }, toThrow(NoProviderError, 'Cannot inject a primitive type of bool! '
269 '(resolving BoolDependency -> bool)'));
270
271 expect(() {
272 injector.get(StringDependency);
273 }, toThrow(NoProviderError, 'Cannot inject a primitive type of String! '
274 '(resolving StringDependency -> String)'));
275 });
276
277
278 it('should throw an exception when circular dependency', () {
279 var injector = injectorFactory([new Module()..type(CircularA)..type(Circul arB)]);
280
281 expect(() {
282 injector.get(CircularA);
283 }, toThrow(CircularDependencyError, 'Cannot resolve a circular dependency! '
284 '(resolving CircularA -> '
285 'CircularB -> CircularA)'));
286 });
287
288
289 it('should provide the injector as Injector', () {
290 var injector = injectorFactory([]);
291
292 expect(injector.get(Injector), toBe(injector));
293 });
294
295
296 // Typedef injection is not supported in dart2js: http://dartbug.com/11612
297 xit('should inject a typedef', () {
298 var module = new Module()..value(CompareInt, compareIntAsc);
299
300 var injector = injectorFactory([module]);
301 var compare = injector.get(CompareInt);
302
303 expect(compare(1, 2), toBe(1));
304 expect(compare(5, 2), toBe(-1));
305 });
306
307
308 // Typedef injection is not supported in dart2js: http://dartbug.com/11612
309 xit('should throw an exception when injecting typedef without providing it', () {
310 var injector = injectorFactory([new Module()..type(WithTypeDefDependency)] );
311
312 expect(() {
313 injector.get(WithTypeDefDependency);
314 }, toThrow(NoProviderError, 'No provider found for CompareInt! '
315 '(resolving WithTypeDefDependency -> CompareInt)'));
316 });
317
318
319 it('should instantiate via the default/unnamed constructor', () {
320 var injector = injectorFactory([new Module()..type(MultipleConstructors)]) ;
321 MultipleConstructors instance = injector.get(MultipleConstructors);
322 expect(instance.instantiatedVia, 'default');
323 });
324
325 // CHILD INJECTORS
326 it('should inject from child', () {
327 var module = new Module()..type(Engine, implementedBy: MockEngine);
328
329 var parent = injectorFactory([new Module()..type(Engine)]);
330 var child = parent.createChild([module]);
331
332 var abcFromParent = parent.get(Engine);
333 var abcFromChild = child.get(Engine);
334
335 expect(abcFromParent.id, toEqual('v8-id'));
336 expect(abcFromChild.id, toEqual('mock-id'));
337 });
338
339
340 it('should enumerate across children', () {
341 var parent = injectorFactory([new Module()..type(Engine)]);
342 var child = parent.createChild([new Module()..type(MockEngine)]);
343
344 expect(parent.types, unorderedEquals(new Set.from([Engine, Injector])));
345 expect(child.types, unorderedEquals(new Set.from([Engine, MockEngine, Inje ctor])));
346 });
347
348
349 it('should inject instance from parent if not provided in child', () {
350 var module = new Module()..type(Car);
351
352 var parent = injectorFactory([new Module()..type(Car)..type(Engine)]);
353 var child = parent.createChild([module]);
354
355 var complexFromParent = parent.get(Car);
356 var complexFromChild = child.get(Car);
357 var abcFromParent = parent.get(Engine);
358 var abcFromChild = child.get(Engine);
359
360 expect(complexFromChild, not(toBe(complexFromParent)));
361 expect(abcFromChild, toBe(abcFromParent));
362 });
363
364
365 it('should inject instance from parent but never use dependency from child', () {
366 var module = new Module()..type(Engine, implementedBy: MockEngine);
367
368 var parent = injectorFactory([new Module()..type(Car)..type(Engine)]);
369 var child = parent.createChild([module]);
370
371 var complexFromParent = parent.get(Car);
372 var complexFromChild = child.get(Car);
373 var abcFromParent = parent.get(Engine);
374 var abcFromChild = child.get(Engine);
375
376 expect(complexFromChild, toBe(complexFromParent));
377 expect(complexFromChild.engine, toBe(abcFromParent));
378 expect(complexFromChild.engine, not(toBe(abcFromChild)));
379 });
380
381
382 it('should force new instance in child even if already instantiated in paren t', () {
383 var parent = injectorFactory([new Module()..type(Engine)]);
384 var abcAlreadyInParent = parent.get(Engine);
385
386 var child = parent.createChild([], forceNewInstances: [Engine]);
387 var abcFromChild = child.get(Engine);
388
389 expect(abcFromChild, not(toBe(abcAlreadyInParent)));
390 });
391
392
393 it('should force new instance in child using provider from grand parent', () {
394 var module = new Module()..type(Engine, implementedBy: MockEngine);
395
396 var grandParent = injectorFactory([module]);
397 var parent = grandParent.createChild([]);
398 var child = parent.createChild([], forceNewInstances: [Engine]);
399
400 var abcFromGrandParent = grandParent.get(Engine);
401 var abcFromChild = child.get(Engine);
402
403 expect(abcFromChild.id, toEqual(('mock-id')));
404 expect(abcFromChild, not(toBe(abcFromGrandParent)));
405 });
406
407
408 it('should provide child injector as Injector', () {
409 var injector = injectorFactory([]);
410 var child = injector.createChild([]);
411
412 expect(child.get(Injector), toBe(child));
413 });
414
415
416 it('should set the injector name', () {
417 var injector = injectorFactory([], 'foo');
418 expect(injector.name, 'foo');
419 });
420
421
422 it('should set the child injector name', () {
423 var injector = injectorFactory([], 'foo');
424 var childInjector = injector.createChild(null, name: 'bar');
425 expect(childInjector.name, 'bar');
426 });
427
428
429 it('should instantiate class only once (Issue #18)', () {
430 var injector = injectorFactory([
431 new Module()
432 ..type(Log)
433 ..type(ClassOne)
434 ..factory(InterfaceOne, (i) => i.get(ClassOne))
435 ]);
436
437 expect(injector.get(InterfaceOne), same(injector.get(ClassOne)));
438 expect(injector.get(Log).log.join(' '), 'ClassOne');
439 });
440
441
442 describe('creation strategy', () {
443
444 it('should get called for instance creation', () {
445
446 List creationLog = [];
447 dynamic creation(Injector requesting, Injector defining, factory) {
448 creationLog.add([requesting, defining]);
449 return factory();
450 }
451
452 var parentModule = new Module()
453 ..type(Engine, implementedBy: MockEngine, creation: creation)
454 ..type(Car, creation: creation);
455
456 var parentInjector = injectorFactory([parentModule]);
457 var childInjector = parentInjector.createChild([]);
458 childInjector.get(Car);
459 expect(creationLog, [
460 [childInjector, parentInjector],
461 [childInjector, parentInjector]
462 ]);
463 });
464
465 it('should be able to prevent instantiation', () {
466
467 List creationLog = [];
468 dynamic creation(Injector requesting, Injector defining, factory) {
469 throw 'not allowing';
470 }
471
472 var module = new Module()
473 ..type(Engine, implementedBy: MockEngine, creation: creation);
474 var injector = injectorFactory([module]);
475 expect(() {
476 injector.get(Engine);
477 }, throwsA('not allowing'));
478 });
479 });
480
481
482 describe('visiblity', () {
483
484 it('should hide instances', () {
485
486 var rootMock = new MockEngine();
487 var childMock = new MockEngine();
488
489 var parentModule = new Module()
490 ..value(Engine, rootMock);
491 var childModule = new Module()
492 ..value(Engine, childMock, visibility: (_, __) => false);
493
494 var parentInjector = injectorFactory([parentModule]);
495 var childInjector = parentInjector.createChild([childModule]);
496
497 var val = childInjector.get(Engine);
498 expect(val, same(rootMock));
499 });
500
501 it('should throw when an instance in not visible in the root injector', () {
502 var module = new Module()
503 ..value(Car, 'Invisible', visibility: (_, __) => false);
504
505 var injector = injectorFactory([module]);
506
507 expect(() {
508 injector.get(Car);
509 }, toThrow(
510 NoProviderError,
511 'No provider found for Car! (resolving Car)'
512 ));
513 });
514
515 });
516
517 });
518
519 }
OLDNEW
« no previous file with comments | « third_party/pkg/di/test/fixed-unittest.dart ('k') | third_party/pkg/di/test_tf_gen.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698