1 /** 2 * Poodinis Dependency Injection Framework 3 * Copyright 2014-2025 Mike Bierlee 4 * This software is licensed under the terms of the MIT license. 5 * The full terms of the license can be found in the LICENSE file. 6 */ 7 8 module poodinis.testclasses; 9 10 version (unittest) : // 11 12 import poodinis; 13 import poodinis.foreigndependencies; 14 15 class ComponentA { 16 } 17 18 class ComponentB { 19 @Inject ComponentA componentA; 20 } 21 22 interface InterfaceA { 23 } 24 25 class ComponentC : InterfaceA { 26 } 27 28 class ComponentD { 29 @Inject InterfaceA componentC = null; 30 private @Inject InterfaceA _privateComponentC = null; 31 32 InterfaceA privateComponentC() { 33 return _privateComponentC; 34 } 35 } 36 37 class DummyAttribute { 38 } 39 40 class ComponentE { 41 @DummyAttribute ComponentC componentC; 42 } 43 44 class ComponentDeclarationCocktail { 45 alias noomer = int; 46 47 @Inject ComponentA componentA; 48 49 void doesNothing() { 50 } 51 52 ~this() { 53 } 54 } 55 56 class ComponentX : InterfaceA { 57 } 58 59 class ComponentZ : ComponentB { 60 } 61 62 class MonkeyShine { 63 @Inject!ComponentX InterfaceA component; 64 } 65 66 class BootstrapBootstrap { 67 @Inject!ComponentX InterfaceA componentX; 68 69 @Inject!ComponentC InterfaceA componentC; 70 } 71 72 class LordOfTheComponents { 73 @Inject InterfaceA[] components; 74 } 75 76 class ComponentCharlie { 77 @Inject @AssignNewInstance ComponentA componentA; 78 } 79 80 class OuttaTime { 81 @Inject @OptionalDependency InterfaceA interfaceA; 82 83 @Inject @OptionalDependency ComponentA componentA; 84 85 @Inject @OptionalDependency ComponentC[] componentCs; 86 } 87 88 class ValuedClass { 89 @Value("values.int") 90 int intValue; 91 92 @Inject ComponentA unrelated; 93 } 94 95 class TestInjector : ValueInjector!int { 96 override int get(string key) { 97 assert(key == "values.int"); 98 return 8; 99 } 100 } 101 102 interface TestInterface { 103 } 104 105 class TestClass : TestInterface { 106 } 107 108 class TestClassDeux : TestInterface { 109 @Inject UnrelatedClass unrelated; 110 } 111 112 class UnrelatedClass { 113 } 114 115 class FailOnCreationClass { 116 this() { 117 throw new Exception("This class should not be instantiated"); 118 } 119 } 120 121 class AutowiredClass { 122 } 123 124 class ComponentClass { 125 @Inject AutowiredClass autowiredClass; 126 } 127 128 class ComponentCat { 129 @Inject ComponentMouse mouse; 130 } 131 132 class ComponentMouse { 133 @Inject ComponentCat cat; 134 } 135 136 class Eenie { 137 @Inject Meenie meenie; 138 } 139 140 class Meenie { 141 @Inject Moe moe; 142 } 143 144 class Moe { 145 @Inject Eenie eenie; 146 } 147 148 class Ittie { 149 @Inject Bittie bittie; 150 } 151 152 class Bittie { 153 @Inject Bunena banana; 154 } 155 156 class Bunena { 157 @Inject Bittie bittie; 158 } 159 160 interface SuperInterface { 161 } 162 163 class SuperImplementation : SuperInterface { 164 @Inject Bunena banana; 165 } 166 167 interface Color { 168 } 169 170 class Blue : Color { 171 } 172 173 class Red : Color { 174 } 175 176 class Spiders { 177 @Inject TestInterface testMember; 178 } 179 180 class Recursive { 181 @Inject Recursive recursive; 182 } 183 184 class Moolah { 185 } 186 187 class Wants { 188 @Inject Moolah moolah; 189 } 190 191 class John { 192 @Inject Wants wants; 193 } 194 195 class Cocktail { 196 @Inject Moolah moolah; 197 198 Red red; 199 200 this(Red red) { 201 this.red = red; 202 } 203 } 204 205 class Wallpaper { 206 Color color; 207 208 this(Color color) { 209 this.color = color; 210 } 211 } 212 213 class Pot { 214 this(Kettle kettle) { 215 } 216 } 217 218 class Kettle { 219 this(Pot pot) { 220 } 221 } 222 223 class Rock { 224 this(Scissors scissors) { 225 } 226 } 227 228 class Paper { 229 this(Rock rock) { 230 } 231 } 232 233 class Scissors { 234 this(Paper paper) { 235 } 236 } 237 238 class Hello { 239 this(Ola ola) { 240 } 241 } 242 243 class PostConstructionDependency { 244 bool postConstructWasCalled = false; 245 246 @PostConstruct void callMeMaybe() { 247 postConstructWasCalled = true; 248 } 249 } 250 251 class ChildOfPostConstruction : PostConstructionDependency { 252 } 253 254 interface ThereWillBePostConstruction { 255 @PostConstruct void constructIt(); 256 } 257 258 class ButThereWontBe : ThereWillBePostConstruction { 259 bool postConstructWasCalled = false; 260 261 override void constructIt() { 262 postConstructWasCalled = true; 263 } 264 } 265 266 class PostConstructWithAutowiring { 267 @Inject private PostConstructionDependency dependency; 268 269 @Value("") 270 private int theNumber = 1; 271 272 @PostConstruct void doIt() { 273 assert(theNumber == 8783); 274 assert(dependency !is null); 275 } 276 } 277 278 class PreDestroyerOfFates { 279 bool preDestroyWasCalled = false; 280 281 @PreDestroy void callMeMaybe() { 282 preDestroyWasCalled = true; 283 } 284 } 285 286 class PostConstructingIntInjector : ValueInjector!int { 287 int get(string key) { 288 return 8783; 289 } 290 } 291 292 interface Fruit { 293 string getShape(); 294 } 295 296 interface Animal { 297 string getYell(); 298 } 299 300 class Banana { 301 string color; 302 303 this(string color) { 304 this.color = color; 305 } 306 } 307 308 class Apple { 309 } 310 311 class Pear : Fruit { 312 override string getShape() { 313 return "Pear shaped"; 314 } 315 } 316 317 class Rabbit : Animal { 318 override string getYell() { 319 return "Squeeeeeel"; 320 } 321 } 322 323 class Wolf : Animal { 324 override string getYell() { 325 return "Wooooooooooo"; 326 } 327 } 328 329 class PieChart { 330 } 331 332 class CakeChart : PieChart { 333 } 334 335 class ClassWrapper { 336 Object someClass; 337 338 this(Object someClass) { 339 this.someClass = someClass; 340 } 341 } 342 343 class ClassWrapperWrapper { 344 ClassWrapper wrapper; 345 346 this(ClassWrapper wrapper) { 347 this.wrapper = wrapper; 348 } 349 } 350 351 class SimpleContext : ApplicationContext { 352 override void registerDependencies(shared(DependencyContainer) container) { 353 container.register!CakeChart; 354 } 355 356 @Component Apple apple() { 357 return new Apple(); 358 } 359 } 360 361 class ComplexAutowiredTestContext : ApplicationContext { 362 363 @Inject private Apple apple; 364 365 @Inject protected ClassWrapper classWrapper; 366 367 override void registerDependencies(shared(DependencyContainer) container) { 368 container.register!Apple; 369 } 370 371 @Component ClassWrapper wrapper() { 372 return new ClassWrapper(apple); 373 } 374 375 @Component ClassWrapperWrapper wrapperWrapper() { 376 return new ClassWrapperWrapper(classWrapper); 377 } 378 379 } 380 381 class AutowiredTestContext : ApplicationContext { 382 383 @Inject private Apple apple; 384 385 @Component ClassWrapper wrapper() { 386 return new ClassWrapper(apple); 387 } 388 } 389 390 class TestContext : ApplicationContext { 391 392 @Component Banana banana() { 393 return new Banana("Yellow"); 394 } 395 396 Apple apple() { 397 return new Apple(); 398 } 399 400 @Component @RegisterByType!Fruit Pear pear() { 401 return new Pear(); 402 } 403 404 @Component @RegisterByType!Animal Rabbit rabbit() { 405 return new Rabbit(); 406 } 407 408 @Component @RegisterByType!Animal Wolf wolf() { 409 return new Wolf(); 410 } 411 412 @Component @Prototype PieChart pieChart() { 413 return new PieChart(); 414 } 415 } 416 417 class TestImplementation : TestInterface { 418 string someContent = ""; 419 } 420 421 class SomeOtherClassThen { 422 } 423 424 class ClassWithConstructor { 425 TestImplementation testImplementation; 426 427 this(TestImplementation testImplementation) { 428 this.testImplementation = testImplementation; 429 } 430 } 431 432 class ClassWithMultipleConstructors { 433 SomeOtherClassThen someOtherClassThen; 434 TestImplementation testImplementation; 435 436 this(SomeOtherClassThen someOtherClassThen) { 437 this.someOtherClassThen = someOtherClassThen; 438 } 439 440 this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { 441 this.someOtherClassThen = someOtherClassThen; 442 this.testImplementation = testImplementation; 443 } 444 } 445 446 class ClassWithConstructorWithMultipleParameters { 447 SomeOtherClassThen someOtherClassThen; 448 TestImplementation testImplementation; 449 450 this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { 451 this.someOtherClassThen = someOtherClassThen; 452 this.testImplementation = testImplementation; 453 } 454 } 455 456 class ClassWithPrimitiveConstructor { 457 SomeOtherClassThen someOtherClassThen; 458 459 this(string willNotBePicked) { 460 } 461 462 this(SomeOtherClassThen someOtherClassThen) { 463 this.someOtherClassThen = someOtherClassThen; 464 } 465 } 466 467 class ClassWithEmptyConstructor { 468 SomeOtherClassThen someOtherClassThen; 469 470 this() { 471 } 472 473 this(SomeOtherClassThen someOtherClassThen) { 474 this.someOtherClassThen = someOtherClassThen; 475 } 476 } 477 478 class ClassWithNonInjectableConstructor { 479 this(string myName) { 480 } 481 } 482 483 class ClassWithStructConstructor { 484 SomeOtherClassThen someOtherClassThen; 485 486 this(Thing willNotBePicked) { 487 } 488 489 this(SomeOtherClassThen someOtherClassThen) { 490 this.someOtherClassThen = someOtherClassThen; 491 } 492 } 493 494 class TestType { 495 } 496 497 class Dependency { 498 } 499 500 struct Thing { 501 int x; 502 } 503 504 class MyConfig { 505 @Value("conf.stuffs") 506 int stuffs; 507 508 @Value("conf.name") 509 string name; 510 511 @Value("conf.thing") 512 Thing thing; 513 } 514 515 class ConfigWithDefaults { 516 @Value("conf.missing") 517 int noms = 9; 518 } 519 520 class ConfigWithMandatory { 521 @MandatoryValue("conf.mustbethere") 522 int nums; 523 } 524 525 class IntInjector : ValueInjector!int { 526 override int get(string key) { 527 assert(key == "conf.stuffs"); 528 return 364; 529 } 530 } 531 532 class StringInjector : ValueInjector!string { 533 override string get(string key) { 534 assert(key == "conf.name"); 535 return "Le Chef"; 536 } 537 } 538 539 class ThingInjector : ValueInjector!Thing { 540 override Thing get(string key) { 541 assert(key == "conf.thing"); 542 return Thing(8899); 543 } 544 } 545 546 class DefaultIntInjector : ValueInjector!int { 547 override int get(string key) { 548 throw new ValueNotAvailableException(key); 549 } 550 } 551 552 class MandatoryAvailableIntInjector : ValueInjector!int { 553 override int get(string key) { 554 return 7466; 555 } 556 } 557 558 class MandatoryUnavailableIntInjector : ValueInjector!int { 559 override int get(string key) { 560 throw new ValueNotAvailableException(key); 561 } 562 } 563 564 class DependencyInjectedIntInjector : ValueInjector!int { 565 @Inject Dependency dependency; 566 567 override int get(string key) { 568 return 2345; 569 } 570 } 571 572 class CircularIntInjector : ValueInjector!int { 573 @Inject ValueInjector!int dependency; 574 575 private int count = 0; 576 577 override int get(string key) { 578 count += 1; 579 if (count >= 3) { 580 return count; 581 } 582 return dependency.get(key); 583 } 584 } 585 586 class ValueInjectedIntInjector : ValueInjector!int { 587 @Value("five") 588 int count = 0; 589 590 override int get(string key) { 591 if (key == "five") { 592 return 5; 593 } 594 595 return count; 596 } 597 } 598 599 class DependencyValueInjectedIntInjector : ValueInjector!int { 600 @Inject ConfigWithDefaults config; 601 602 override int get(string key) { 603 if (key == "conf.missing") { 604 return 8899; 605 } 606 607 return 0; 608 } 609 } 610 611 class TemplatedComponent(T) { 612 @Inject T instance; 613 } 614 615 class CircularTemplateComponentA : TemplatedComponent!CircularTemplateComponentB { 616 617 } 618 619 class CircularTemplateComponentB : TemplatedComponent!CircularTemplateComponentA { 620 621 } 622 623 class ClassWithTemplatedConstructorArg(T) { 624 TemplatedComponent!T dependency; 625 626 this(TemplatedComponent!T assignedDependency) { 627 this.dependency = assignedDependency; 628 } 629 } 630 631 class Grandma { 632 633 } 634 635 class Mommy : Grandma { 636 637 } 638 639 class Kid : Mommy { 640 641 } 642 643 class AutowiredMethod { 644 @Inject 645 int lala() { 646 return 42; 647 } 648 649 @Inject 650 int lala(int valla) { 651 return valla; 652 } 653 } 654 655 class WithAutowireAttribute { 656 @Autowire ComponentA componentA; 657 }