From ca9cdfb33a823fb10fe5883f3c7b036ab974e103 Mon Sep 17 00:00:00 2001 From: Willian Marchesan Date: Fri, 26 Jan 2024 21:58:42 -0300 Subject: [PATCH 1/4] Doc: Added various Future tests --- lib/src/exception/bean_not_found.dart | 2 +- test/beans_test/application_future_test.dart | 262 ++++++++++++++++++ test/beans_test/application_test.dart | 14 +- test/beans_test/dependent_future_test.dart | 198 +++++++++++++ test/beans_test/object_future_test.dart | 66 +++++ test/beans_test/session_future_test.dart | 247 +++++++++++++++++ test/beans_test/singleton_future_test.dart | 181 ++++++++++++ .../application_destroy_get.dart | 0 .../application_destroy_register.dart | 0 test/dart_ddi_test.dart | 12 + 10 files changed, 976 insertions(+), 6 deletions(-) create mode 100644 test/beans_test/application_future_test.dart create mode 100644 test/beans_test/dependent_future_test.dart create mode 100644 test/beans_test/object_future_test.dart create mode 100644 test/beans_test/session_future_test.dart create mode 100644 test/beans_test/singleton_future_test.dart rename test/{beans_test => clazz_samples}/application_destroy_get.dart (100%) rename test/{beans_test => clazz_samples}/application_destroy_register.dart (100%) diff --git a/lib/src/exception/bean_not_found.dart b/lib/src/exception/bean_not_found.dart index 15ed80b..ab63acf 100644 --- a/lib/src/exception/bean_not_found.dart +++ b/lib/src/exception/bean_not_found.dart @@ -4,6 +4,6 @@ class BeanNotFound implements Exception { @override String toString() { - return 'No Instance with Type $cause is found.'; + return 'No Instance found with Type $cause.'; } } diff --git a/test/beans_test/application_future_test.dart b/test/beans_test/application_future_test.dart new file mode 100644 index 0000000..736e016 --- /dev/null +++ b/test/beans_test/application_future_test.dart @@ -0,0 +1,262 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/a.dart'; +import '../clazz_samples/b.dart'; +import '../clazz_samples/c.dart'; +import '../clazz_samples/undestroyable/application_destroy_get.dart'; + +void applicationFuture() { + group('DDI Application Future Basic Tests', () { + void registerApplicationBeans() { + DDI.instance.registerApplication(() async => A(await DDI.instance())); + DDI.instance.registerApplication>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerApplication(C.new); + } + + void removeApplicationBeans() { + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + } + + test('Register and retrieve Application bean', () async { + registerApplicationBeans(); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeApplicationBeans(); + }); + + test('Retrieve Application bean after a "child" bean is diposed', () async { + registerApplicationBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeApplicationBeans(); + }); + + test('Retrieve Application bean after a second "child" bean is diposed', () async { + registerApplicationBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose>(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeApplicationBeans(); + }); + + test('Retrieve Application bean after the last "child" bean is diposed', () async { + registerApplicationBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(true, identical(instance1.b, instance2.b)); + expect(true, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeApplicationBeans(); + }); + + test('Retrieve Application bean after 2 "child" bean is diposed', () async { + registerApplicationBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose>(); + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(true, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeApplicationBeans(); + }); + + test('Retrieve Application bean after 3 "child" bean is diposed', () async { + registerApplicationBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + DDI.instance.dispose>(); + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(false, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeApplicationBeans(); + }); + + test('Try to retrieve Application bean after disposed', () { + DDI.instance.registerApplication(() => Future.value(C())); + + final instance1 = DDI.instance.get>(); + + DDI.instance.dispose>(); + + final instance2 = DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + + DDI.instance.destroy>(); + }); + + test('Try to retrieve Application bean after removed', () { + DDI.instance.registerApplication(() => Future.value(C())); + + DDI.instance.get>(); + + DDI.instance.destroy>(); + + expect(() => DDI.instance.get>(), throwsA(isA())); + }); + + test('Create, get and remove a qualifier bean', () { + DDI.instance.registerApplication(() => Future.value(C()), qualifier: 'typeC'); + + DDI.instance.get(qualifier: 'typeC'); + + DDI.instance.destroy(qualifier: 'typeC'); + + expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + }); + + test('Try to destroy a undestroyable Application bean', () { + DDI.instance.registerApplication(() => Future.value(ApplicationDestroyGet()), destroyable: false); + + final instance1 = DDI.instance.get>(); + + DDI.instance.destroy>(); + + final instance2 = DDI.instance.get>(); + + expect(instance1, same(instance2)); + }); + test('Register and retrieve Future Application', () async { + DDI.instance.registerApplication(() async => A(await DDI.instance>())); + DDI.instance.registerApplication(() async => B(DDI.instance())); + DDI.instance.registerApplication(C.new); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Register and retrieve Future delayed Application bean', () async { + DDI.instance.registerApplication(() async { + final C value = await Future.delayed(const Duration(seconds: 2), C.new); + return value; + }); + + final C intance = await DDI.instance.get>(); + + DDI.instance.destroy>(qualifier: 'typeC'); + + await expectLater(intance.value, 1); + }); + + test('Try to retrieve Application bean using Future', () async { + DDI.instance.registerApplication(() async => A(await DDI.instance())); + DDI.instance.registerApplication(() async => B(DDI.instance())); + DDI.instance.registerApplication(C.new); + + //This happens because A(await DDI.instance()) transform to A(await DDI.instance>()) + expect(() => DDI.instance.get>(), throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Register and retrieve Application bean using FutureOr', () async { + DDI.instance.registerApplication(() async => A(await DDI.instance())); + DDI.instance.registerApplication>(() async => B(DDI.instance())); + DDI.instance.registerApplication(C.new); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + test('Retrieve Application bean after a "child" bean is disposed using Future', () async { + DDI.instance.registerApplication(() async => A(await DDI.instance())); + DDI.instance.registerApplication>(() async => B(DDI.instance())); + DDI.instance.registerApplication(C.new); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Retrieve Application bean Stream', () async { + DDI.instance.registerApplication(StreamController.new); + + final StreamController streamController = DDI.instance(); + + streamController.add(C()); + streamController.close(); + + final instance = await streamController.stream.first; + + expect(instance, isA()); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/application_test.dart b/test/beans_test/application_test.dart index 55e2066..6647db2 100644 --- a/test/beans_test/application_test.dart +++ b/test/beans_test/application_test.dart @@ -14,7 +14,7 @@ void application() { void registerApplicationBeans() { DDI.instance.registerApplication(() => A(DDI.instance())); DDI.instance.registerApplication(() => B(DDI.instance())); - DDI.instance.registerApplication(() => C()); + DDI.instance.registerApplication(C.new); } void removeApplicationBeans() { @@ -121,7 +121,7 @@ void application() { }); test('Try to retrieve Application bean after disposed', () { - DDI.instance.registerApplication(() => C()); + DDI.instance.registerApplication(C.new); final instance1 = DDI.instance.get(); @@ -130,9 +130,13 @@ void application() { final instance2 = DDI.instance.get(); expect(false, identical(instance1, instance2)); + + DDI.instance.destroy(); }); test('Try to retrieve Application bean after removed', () { + DDI.instance.registerApplication(C.new); + DDI.instance.get(); DDI.instance.destroy(); @@ -141,7 +145,7 @@ void application() { }); test('Create, get and remove a qualifier bean', () { - DDI.instance.registerApplication(() => C(), qualifier: 'typeC'); + DDI.instance.registerApplication(C.new, qualifier: 'typeC'); DDI.instance.get(qualifier: 'typeC'); @@ -152,7 +156,7 @@ void application() { }); test('Try to destroy a undestroyable Application bean', () { - DDI.instance.registerApplication(() => ApplicationDestroyGet(), + DDI.instance.registerApplication(ApplicationDestroyGet.new, destroyable: false); final instance1 = DDI.instance.get(); @@ -165,7 +169,7 @@ void application() { }); test('Try to register again a undestroyable Application bean', () { - DDI.instance.registerApplication(() => ApplicationDestroyRegister(), + DDI.instance.registerApplication(ApplicationDestroyRegister.new, destroyable: false); DDI.instance.get(); diff --git a/test/beans_test/dependent_future_test.dart b/test/beans_test/dependent_future_test.dart new file mode 100644 index 0000000..a85271b --- /dev/null +++ b/test/beans_test/dependent_future_test.dart @@ -0,0 +1,198 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/a.dart'; +import '../clazz_samples/b.dart'; +import '../clazz_samples/c.dart'; +import '../clazz_samples/undestroyable/dependent_destroy_get.dart'; + +void dependentFuture() { + group('DDI Dependent Future Basic Tests', () { + void registerDependentBeans() { + DDI.instance.registerDependent(() async => A(await DDI.instance())); + DDI.instance.registerDependent>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerDependent(C.new); + } + + void removeDependentBeans() { + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + } + + test('Register and retrieve Dependent bean', () async { + registerDependentBeans(); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(false, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeDependentBeans(); + }); + + test('Retrieve Dependent bean after a "child" bean is diposed', () async { + registerDependentBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance1 = await DDI.instance.get>(); + expect(false, identical(instance1, instance)); + expect(false, identical(instance1.b, instance.b)); + expect(false, identical(instance1.b.c, instance.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeDependentBeans(); + }); + + test('Retrieve Dependent bean after a second "child" bean is diposed', () async { + registerDependentBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose>(); + final instance1 = await DDI.instance.get>(); + expect(false, identical(instance1, instance)); + expect(false, identical(instance1.b, instance.b)); + expect(false, identical(instance1.b.c, instance.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeDependentBeans(); + }); + + test('Try to retrieve Dependent bean after disposed', () { + DDI.instance.registerDependent(() => Future.value(C())); + + final instance1 = DDI.instance.get>(); + + DDI.instance.dispose>(); + + final instance2 = DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + + DDI.instance.destroy>(); + }); + + test('Try to retrieve Dependent bean after removed', () { + DDI.instance.registerDependent(() => Future.value(C())); + + DDI.instance.get>(); + + DDI.instance.destroy>(); + + expect(() => DDI.instance.get>(), throwsA(isA())); + }); + + test('Create, get and remove a qualifier bean', () { + DDI.instance.registerDependent(() => Future.value(C()), qualifier: 'typeC'); + + final instance1 = DDI.instance.get(qualifier: 'typeC'); + final instance2 = DDI.instance.get(qualifier: 'typeC'); + + expect(false, identical(instance1, instance2)); + + DDI.instance.destroy(qualifier: 'typeC'); + + expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + }); + + test('Try to destroy a undestroyable Dependent bean', () { + DDI.instance.registerDependent(() => Future.value(DependentDestroyGet()), destroyable: false); + + final Future instance1 = DDI.instance.get(); + + DDI.instance.destroy>(); + + final instance2 = DDI.instance.get>(); + + expect(instance2, isNotNull); + expect(false, identical(instance1, instance2)); + }); + + test('Register and retrieve Future delayed Dependent bean', () async { + DDI.instance.registerDependent(() async { + final C value = await Future.delayed(const Duration(seconds: 2), C.new); + return value; + }); + + final C intance = await DDI.instance.get>(); + + DDI.instance.destroy>(qualifier: 'typeC'); + + await expectLater(intance.value, 1); + }); + + test('Try to retrieve Dependent bean using Future', () async { + DDI.instance.registerDependent(() async => A(await DDI.instance())); + DDI.instance.registerDependent(() async => B(DDI.instance())); + DDI.instance.registerDependent(C.new); + + //This happens because A(await DDI.instance()) transform to A(await DDI.instance>()) + expect(() => DDI.instance.get>(), throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Register and retrieve Dependent bean using FutureOr', () async { + DDI.instance.registerDependent(() async => A(await DDI.instance())); + DDI.instance.registerDependent>(() async => B(DDI.instance())); + DDI.instance.registerDependent(C.new); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(false, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance1.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + test('Retrieve Dependent bean after a "child" bean is disposed using Future', () async { + DDI.instance.registerDependent(() async => A(await DDI.instance())); + DDI.instance.registerDependent>(() async => B(DDI.instance())); + DDI.instance.registerDependent(C.new); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(false, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance1.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Retrieve Dependent bean Stream', () async { + DDI.instance.registerDependent(StreamController.new); + + final StreamController streamController = DDI.instance(); + + streamController.add(C()); + streamController.close(); + + final instance = await streamController.stream.first; + + expect(instance, isA()); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/object_future_test.dart b/test/beans_test/object_future_test.dart new file mode 100644 index 0000000..3c08c91 --- /dev/null +++ b/test/beans_test/object_future_test.dart @@ -0,0 +1,66 @@ +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +void objectFuture() { + group('DDI Object Future Basic Tests', () { + test('Register and retrieve object bean', () async { + DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'futureAuthor'); + + final instance1 = await DDI.instance.get>(qualifier: 'futureAuthor'); + final instance2 = await DDI.instance.get>(qualifier: 'futureAuthor'); + + expect('Willian Marchesan', instance1); + expect(instance1, same(instance2)); + + DDI.instance.destroy(qualifier: 'futureAuthor'); + }); + + test('Try to retrieve object bean after removed', () { + DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'futureAuthor'); + + DDI.instance.get(qualifier: 'futureAuthor'); + + DDI.instance.destroy(qualifier: 'futureAuthor'); + + expect(() => DDI.instance.get(qualifier: 'futureAuthor'), throwsA(isA())); + }); + + test('Try to destroy a undestroyable Object bean', () async { + DDI.instance.registerObject( + Future.value('Willian Marchesan'), + qualifier: 'futureAuthor', + destroyable: false, + ); + + final instance1 = await DDI.instance.get>(qualifier: 'futureAuthor'); + + DDI.instance.destroy(qualifier: 'futureAuthor'); + + final String instance2 = await DDI.instance.get(qualifier: 'futureAuthor'); + + expect('Willian Marchesan', instance1); + expect(instance1, same(instance2)); + }); + + test('Register, retrieve and refresh object bean', () async { + DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'name'); + + final instance1 = await DDI.instance.get>(qualifier: 'name'); + final instance2 = await DDI.instance.get>(qualifier: 'name'); + + expect('Willian Marchesan', instance1); + expect(instance1, same(instance2)); + + DDI.instance.refreshObject(Future.value('Will'), qualifier: 'name'); + + final String instance3 = await DDI.instance.get>(qualifier: 'name'); + + expect('Will', instance3); + expect(false, identical(instance1, instance3)); + expect(false, identical(instance2, instance3)); + + DDI.instance.destroy(qualifier: 'name'); + }); + }); +} diff --git a/test/beans_test/session_future_test.dart b/test/beans_test/session_future_test.dart new file mode 100644 index 0000000..0b73393 --- /dev/null +++ b/test/beans_test/session_future_test.dart @@ -0,0 +1,247 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/a.dart'; +import '../clazz_samples/b.dart'; +import '../clazz_samples/c.dart'; +import '../clazz_samples/undestroyable/session_destroy_get.dart'; + +void sessionFuture() { + group('DDI Session Future Basic Tests', () { + void registerSessionBeans() { + DDI.instance.registerSession(() async => A(await DDI.instance())); + DDI.instance.registerSession>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerSession(C.new); + } + + void removeSessionBeans() { + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + } + + test('Register and retrieve Session bean', () async { + registerSessionBeans(); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeSessionBeans(); + }); + + test('Retrieve Session bean after a "child" bean is diposed', () async { + registerSessionBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeSessionBeans(); + }); + + test('Retrieve Session bean after a second "child" bean is diposed', () async { + registerSessionBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.dispose(); + DDI.instance.dispose>(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeSessionBeans(); + }); + + test('Retrieve Session bean after the last "child" bean is diposed', () async { + registerSessionBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(true, identical(instance1.b, instance2.b)); + expect(true, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeSessionBeans(); + }); + + test('Retrieve Session bean after 2 "child" bean is diposed', () async { + registerSessionBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose>(); + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(true, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeSessionBeans(); + }); + + test('Retrieve Session bean after 3 "child" bean is diposed', () async { + registerSessionBeans(); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + DDI.instance.dispose>(); + DDI.instance.dispose>(); + final instance2 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + expect(false, identical(instance1.b, instance2.b)); + expect(false, identical(instance1.b.c, instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeSessionBeans(); + }); + + test('Try to retrieve Session bean after disposed', () { + DDI.instance.destroy>(); + + DDI.instance.registerSession(() => Future.value(C())); + + final instance1 = DDI.instance.get>(); + + DDI.instance.dispose>(); + + final instance2 = DDI.instance.get>(); + + expect(false, identical(instance1, instance2)); + DDI.instance.destroy>(); + }); + + test('Try to retrieve Session bean after removed', () { + DDI.instance.registerSession(() => Future.value(C())); + + DDI.instance.get>(); + + DDI.instance.destroy>(); + + expect(() => DDI.instance.get>(), throwsA(isA())); + }); + + test('Create, get and remove a qualifier bean', () { + DDI.instance.registerSession(() => Future.value(C()), qualifier: 'typeC'); + + DDI.instance.get(qualifier: 'typeC'); + + DDI.instance.destroy(qualifier: 'typeC'); + + expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + }); + + test('Try to destroy a undestroyable Session bean', () { + DDI.instance.registerSession(() => Future.value(SessionDestroyGet()), destroyable: false); + + final instance1 = DDI.instance.get>(); + + DDI.instance.destroy>(); + + final instance2 = DDI.instance.get>(); + + expect(instance1, same(instance2)); + }); + + test('Register and retrieve Future delayed Session bean', () async { + DDI.instance.registerSession(() async { + final C value = await Future.delayed(const Duration(seconds: 2), C.new); + return value; + }); + + final C intance = await DDI.instance.get>(); + + DDI.instance.destroy>(qualifier: 'typeC'); + + await expectLater(intance.value, 1); + }); + + test('Try to retrieve Session bean using Future', () async { + DDI.instance.registerSession(() async => A(await DDI.instance())); + DDI.instance.registerSession(() async => B(DDI.instance())); + DDI.instance.registerSession(C.new); + + //This happens because A(await DDI.instance()) transform to A(await DDI.instance>()) + expect(() => DDI.instance.get>(), throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Register and retrieve Session bean using FutureOr', () async { + DDI.instance.registerSession(() async => A(await DDI.instance())); + DDI.instance.registerSession>(() async => B(DDI.instance())); + DDI.instance.registerSession(C.new); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + test('Retrieve Session bean after a "child" bean is disposed using Future', () async { + DDI.instance.registerSession(() async => A(await DDI.instance())); + DDI.instance.registerSession>(() async => B(DDI.instance())); + DDI.instance.registerSession(C.new); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Retrieve Session bean Stream', () async { + DDI.instance.registerSession(StreamController.new); + + final StreamController streamController = DDI.instance(); + + streamController.add(C()); + streamController.close(); + + final instance = await streamController.stream.first; + + expect(instance, isA()); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/singleton_future_test.dart b/test/beans_test/singleton_future_test.dart new file mode 100644 index 0000000..abe3b61 --- /dev/null +++ b/test/beans_test/singleton_future_test.dart @@ -0,0 +1,181 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/a.dart'; +import '../clazz_samples/b.dart'; +import '../clazz_samples/c.dart'; +import '../clazz_samples/undestroyable/singleton_destroy_get.dart'; + +void singletonFuture() { + group('DDI Singleton Future Basic Tests', () { + void registerSingletonBeans() { + DDI.instance.registerApplication(C.new); + DDI.instance.registerApplication>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerApplication(() async => A(await DDI.instance())); + } + + void removeSingletonBeans() { + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + } + + test('Register and retrieve singleton bean', () async { + ///Where is Singleton, should the register in the correct order + registerSingletonBeans(); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + removeSingletonBeans(); + }); + + test('Retrieve singleton bean after a "child" bean is diposed', () async { + registerSingletonBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.destroy(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeSingletonBeans(); + }); + + test('Retrieve singleton bean after a second "child" bean is diposed', () async { + registerSingletonBeans(); + + final instance = await DDI.instance.get>(); + + DDI.instance.destroy>(); + final instance1 = await DDI.instance.get>(); + expect(instance1, same(instance)); + expect(instance1.b, same(instance.b)); + expect(instance.b.c, same(instance1.b.c)); + expect(instance.b.c.value, same(instance1.b.c.value)); + + removeSingletonBeans(); + }); + + test('Try to retrieve singleton bean after removed', () { + DDI.instance.registerSingleton(() => Future.value(C())); + + DDI.instance.get>(); + + DDI.instance.destroy>(); + + expect(() => DDI.instance.get>(), throwsA(isA())); + }); + + test('Create, get and remove a qualifier bean', () { + DDI.instance.registerSingleton(() => Future.value(C()), qualifier: 'typeC'); + + DDI.instance.get(qualifier: 'typeC'); + + DDI.instance.destroy(qualifier: 'typeC'); + + expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + }); + + test('Try to destroy a undestroyable Singleton bean', () { + DDI.instance.registerSingleton(() => Future.value(SingletonDestroyGet()), destroyable: false); + + final instance1 = DDI.instance.get>(); + + DDI.instance.destroy>(); + + final instance2 = DDI.instance.get>(); + + expect(instance1, same(instance2)); + }); + + test('Register and retrieve Future delayed Singleton bean', () async { + DDI.instance.registerSingleton(() async { + final C value = await Future.delayed(const Duration(seconds: 2), C.new); + return value; + }); + + final C intance = await DDI.instance.get>(); + + DDI.instance.destroy>(qualifier: 'typeC'); + + await expectLater(intance.value, 1); + }); + + test('Try to retrieve Singleton bean using Future', () async { + DDI.instance.registerSingleton(C.new); + DDI.instance.registerSingleton(() async => B(DDI.instance())); + DDI.instance.registerSingleton(() async => A(await DDI.instance())); + + //This happens because A(await DDI.instance()) transform to A(await DDI.instance>()) + expect(() => DDI.instance.get>(), throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Register and retrieve Singleton bean using FutureOr', () async { + DDI.instance.registerSingleton(C.new); + DDI.instance.registerSingleton>(() async => B(DDI.instance())); + DDI.instance.registerSingleton(() async => A(await DDI.instance())); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + test('Retrieve Singleton bean after a "child" bean is disposed using Future', () async { + DDI.instance.registerSingleton(C.new); + DDI.instance.registerSingleton>(() async => B(DDI.instance())); + DDI.instance.registerSingleton(() async => A(await DDI.instance())); + + final instance1 = await DDI.instance.get>(); + + DDI.instance.dispose(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + DDI.instance.destroy(); + }); + + test('Retrieve Singleton bean Stream', () async { + DDI.instance.registerSingleton(StreamController.new); + + final StreamController streamController = DDI.instance(); + + streamController.add(C()); + streamController.close(); + + final instance = await streamController.stream.first; + + expect(instance, isA()); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/application_destroy_get.dart b/test/clazz_samples/application_destroy_get.dart similarity index 100% rename from test/beans_test/application_destroy_get.dart rename to test/clazz_samples/application_destroy_get.dart diff --git a/test/beans_test/application_destroy_register.dart b/test/clazz_samples/application_destroy_register.dart similarity index 100% rename from test/beans_test/application_destroy_register.dart rename to test/clazz_samples/application_destroy_register.dart diff --git a/test/dart_ddi_test.dart b/test/dart_ddi_test.dart index 8547523..7c06912 100644 --- a/test/dart_ddi_test.dart +++ b/test/dart_ddi_test.dart @@ -1,14 +1,19 @@ import 'beans_test/add_decoratos_test.dart'; +import 'beans_test/application_future_test.dart'; import 'beans_test/application_test.dart'; import 'beans_test/circular_injection_test.dart'; +import 'beans_test/dependent_future_test.dart'; import 'beans_test/dependent_test.dart'; import 'beans_test/dispose_destroy_all_session_test.dart'; import 'beans_test/get_by_type_test.dart'; import 'beans_test/interceptor_test.dart'; +import 'beans_test/object_future_test.dart'; import 'beans_test/object_test.dart'; import 'beans_test/post_construct_pre_destroy_test.dart'; import 'beans_test/register_if_test.dart'; +import 'beans_test/session_future_test.dart'; import 'beans_test/session_test.dart'; +import 'beans_test/singleton_future_test.dart'; import 'beans_test/singleton_test.dart'; import 'event_test/event_test.dart'; import 'stream_test/stream_test.dart'; @@ -26,6 +31,13 @@ void main() { registerIf(); postConstructPreDestroyTest(); + //Futures + applicationFuture(); + singletonFuture(); + sessionFuture(); + dependentFuture(); + objectFuture(); + //Decorators addDecorator(); From 11a079486fc3e46fc0f7e37b99a5238c790a620d Mon Sep 17 00:00:00 2001 From: Willian Marchesan Date: Fri, 26 Jan 2024 22:50:29 -0300 Subject: [PATCH 2/4] Doc: Fix PostConstruct and PreDestroy in Future instances --- lib/src/core/bean/dart_ddi_impl.dart | 31 +++- test/beans_test/application_future_test.dart | 32 ++-- test/beans_test/application_test.dart | 4 +- test/beans_test/dependent_future_test.dart | 25 +++- .../dispose_destroy_all_session_test.dart | 38 ++++- ...uture_post_construct_pre_destroy_test.dart | 74 ++++++++++ test/beans_test/get_by_future_type_test.dart | 137 ++++++++++++++++++ test/beans_test/get_by_type_test.dart | 3 - test/beans_test/object_future_test.dart | 33 +++-- .../post_construct_pre_destroy_test.dart | 20 ++- test/beans_test/session_future_test.dart | 18 ++- test/beans_test/singleton_future_test.dart | 25 +++- test/clazz_samples/l.dart | 2 +- test/dart_ddi_test.dart | 5 + 14 files changed, 387 insertions(+), 60 deletions(-) create mode 100644 test/beans_test/future_post_construct_pre_destroy_test.dart create mode 100644 test/beans_test/get_by_future_type_test.dart diff --git a/lib/src/core/bean/dart_ddi_impl.dart b/lib/src/core/bean/dart_ddi_impl.dart index 571e932..3f29c42 100644 --- a/lib/src/core/bean/dart_ddi_impl.dart +++ b/lib/src/core/bean/dart_ddi_impl.dart @@ -43,6 +43,8 @@ class _DDIImpl implements DDI { if (clazz is PostConstruct) { clazz.onPostConstruct(); + } else if (clazz is Future) { + _runFutureOrPostConstruct(clazz); } _beans[effectiveQualifierName] = FactoryClazz( @@ -191,6 +193,8 @@ class _DDIImpl implements DDI { if (register is PostConstruct) { register.onPostConstruct(); + } else if (register is Future) { + _runFutureOrPostConstruct(register); } _beans[effectiveQualifierName] = FactoryClazz( @@ -244,6 +248,8 @@ class _DDIImpl implements DDI { if (applicationClazz is PostConstruct) { applicationClazz.onPostConstruct(); + } else if (applicationClazz is Future) { + _runFutureOrPostConstruct(applicationClazz); } factoryClazz.clazzInstance = applicationClazz; @@ -276,6 +282,8 @@ class _DDIImpl implements DDI { if (dependentClazz is PostConstruct) { dependentClazz.onPostConstruct(); + } else if (dependentClazz is Future) { + _runFutureOrPostConstruct(dependentClazz); } if (factoryClazz.interceptors case final inter?) { @@ -360,7 +368,7 @@ class _DDIImpl implements DDI { _destroy(effectiveQualifierName); } - void _destroy(effectiveQualifierName) { + void _destroy(Object effectiveQualifierName) { if (_beans[effectiveQualifierName] case final factoryClazz? when factoryClazz.destroyable) { //Only destroy if destroyable was registered with true @@ -371,8 +379,10 @@ class _DDIImpl implements DDI { } } - if (clazz is PreDestroy) { - clazz.onPreDestroy(); + if (clazz is FutureOr) { + _runFutureOrPreDestroy(clazz, effectiveQualifierName); + //Should return because the _runFutureOrPreDestroy apply the remove + return; } } @@ -541,4 +551,19 @@ class _DDIImpl implements DDI { factoryClazz.clazzInstance = _executarDecorators(register, factoryClazz.decorators); } + + void _runFutureOrPostConstruct(Future register) async { + final PostConstruct clazz = await register; + + clazz.onPostConstruct(); + } + + Future _runFutureOrPreDestroy( + FutureOr register, Object effectiveQualifierName) async { + final PreDestroy clazz = await register; + + clazz.onPreDestroy(); + + _beans.remove(effectiveQualifierName); + } } diff --git a/test/beans_test/application_future_test.dart b/test/beans_test/application_future_test.dart index 736e016..f063658 100644 --- a/test/beans_test/application_future_test.dart +++ b/test/beans_test/application_future_test.dart @@ -13,7 +13,8 @@ void applicationFuture() { group('DDI Application Future Basic Tests', () { void registerApplicationBeans() { DDI.instance.registerApplication(() async => A(await DDI.instance())); - DDI.instance.registerApplication>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerApplication>( + () => Future.value(B(DDI.instance()))); DDI.instance.registerApplication(C.new); } @@ -52,7 +53,8 @@ void applicationFuture() { removeApplicationBeans(); }); - test('Retrieve Application bean after a second "child" bean is diposed', () async { + test('Retrieve Application bean after a second "child" bean is diposed', + () async { registerApplicationBeans(); final instance = await DDI.instance.get>(); @@ -67,7 +69,8 @@ void applicationFuture() { removeApplicationBeans(); }); - test('Retrieve Application bean after the last "child" bean is diposed', () async { + test('Retrieve Application bean after the last "child" bean is diposed', + () async { registerApplicationBeans(); final instance1 = await DDI.instance.get>(); @@ -143,17 +146,21 @@ void applicationFuture() { }); test('Create, get and remove a qualifier bean', () { - DDI.instance.registerApplication(() => Future.value(C()), qualifier: 'typeC'); + DDI.instance + .registerApplication(() => Future.value(C()), qualifier: 'typeC'); DDI.instance.get(qualifier: 'typeC'); DDI.instance.destroy(qualifier: 'typeC'); - expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + expect(() => DDI.instance.get(qualifier: 'typeC'), + throwsA(isA())); }); test('Try to destroy a undestroyable Application bean', () { - DDI.instance.registerApplication(() => Future.value(ApplicationDestroyGet()), destroyable: false); + DDI.instance.registerApplication( + () => Future.value(ApplicationDestroyGet()), + destroyable: false); final instance1 = DDI.instance.get>(); @@ -164,7 +171,8 @@ void applicationFuture() { expect(instance1, same(instance2)); }); test('Register and retrieve Future Application', () async { - DDI.instance.registerApplication(() async => A(await DDI.instance>())); + DDI.instance + .registerApplication(() async => A(await DDI.instance>())); DDI.instance.registerApplication(() async => B(DDI.instance())); DDI.instance.registerApplication(C.new); @@ -209,7 +217,8 @@ void applicationFuture() { test('Register and retrieve Application bean using FutureOr', () async { DDI.instance.registerApplication(() async => A(await DDI.instance())); - DDI.instance.registerApplication>(() async => B(DDI.instance())); + DDI.instance + .registerApplication>(() async => B(DDI.instance())); DDI.instance.registerApplication(C.new); final instance1 = await DDI.instance.get>(); @@ -224,9 +233,12 @@ void applicationFuture() { DDI.instance.destroy>(); DDI.instance.destroy(); }); - test('Retrieve Application bean after a "child" bean is disposed using Future', () async { + test( + 'Retrieve Application bean after a "child" bean is disposed using Future', + () async { DDI.instance.registerApplication(() async => A(await DDI.instance())); - DDI.instance.registerApplication>(() async => B(DDI.instance())); + DDI.instance + .registerApplication>(() async => B(DDI.instance())); DDI.instance.registerApplication(C.new); final instance1 = await DDI.instance.get>(); diff --git a/test/beans_test/application_test.dart b/test/beans_test/application_test.dart index 6647db2..9605b7c 100644 --- a/test/beans_test/application_test.dart +++ b/test/beans_test/application_test.dart @@ -156,8 +156,8 @@ void application() { }); test('Try to destroy a undestroyable Application bean', () { - DDI.instance.registerApplication(ApplicationDestroyGet.new, - destroyable: false); + DDI.instance + .registerApplication(ApplicationDestroyGet.new, destroyable: false); final instance1 = DDI.instance.get(); diff --git a/test/beans_test/dependent_future_test.dart b/test/beans_test/dependent_future_test.dart index a85271b..cb4991b 100644 --- a/test/beans_test/dependent_future_test.dart +++ b/test/beans_test/dependent_future_test.dart @@ -13,7 +13,8 @@ void dependentFuture() { group('DDI Dependent Future Basic Tests', () { void registerDependentBeans() { DDI.instance.registerDependent(() async => A(await DDI.instance())); - DDI.instance.registerDependent>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerDependent>( + () => Future.value(B(DDI.instance()))); DDI.instance.registerDependent(C.new); } @@ -52,7 +53,8 @@ void dependentFuture() { removeDependentBeans(); }); - test('Retrieve Dependent bean after a second "child" bean is diposed', () async { + test('Retrieve Dependent bean after a second "child" bean is diposed', + () async { registerDependentBeans(); final instance = await DDI.instance.get>(); @@ -92,7 +94,8 @@ void dependentFuture() { }); test('Create, get and remove a qualifier bean', () { - DDI.instance.registerDependent(() => Future.value(C()), qualifier: 'typeC'); + DDI.instance + .registerDependent(() => Future.value(C()), qualifier: 'typeC'); final instance1 = DDI.instance.get(qualifier: 'typeC'); final instance2 = DDI.instance.get(qualifier: 'typeC'); @@ -101,11 +104,13 @@ void dependentFuture() { DDI.instance.destroy(qualifier: 'typeC'); - expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + expect(() => DDI.instance.get(qualifier: 'typeC'), + throwsA(isA())); }); test('Try to destroy a undestroyable Dependent bean', () { - DDI.instance.registerDependent(() => Future.value(DependentDestroyGet()), destroyable: false); + DDI.instance.registerDependent(() => Future.value(DependentDestroyGet()), + destroyable: false); final Future instance1 = DDI.instance.get(); @@ -145,7 +150,8 @@ void dependentFuture() { test('Register and retrieve Dependent bean using FutureOr', () async { DDI.instance.registerDependent(() async => A(await DDI.instance())); - DDI.instance.registerDependent>(() async => B(DDI.instance())); + DDI.instance + .registerDependent>(() async => B(DDI.instance())); DDI.instance.registerDependent(C.new); final instance1 = await DDI.instance.get>(); @@ -160,9 +166,12 @@ void dependentFuture() { DDI.instance.destroy>(); DDI.instance.destroy(); }); - test('Retrieve Dependent bean after a "child" bean is disposed using Future', () async { + test( + 'Retrieve Dependent bean after a "child" bean is disposed using Future', + () async { DDI.instance.registerDependent(() async => A(await DDI.instance())); - DDI.instance.registerDependent>(() async => B(DDI.instance())); + DDI.instance + .registerDependent>(() async => B(DDI.instance())); DDI.instance.registerDependent(C.new); final instance1 = await DDI.instance.get>(); diff --git a/test/beans_test/dispose_destroy_all_session_test.dart b/test/beans_test/dispose_destroy_all_session_test.dart index 2b0c197..02a3af7 100644 --- a/test/beans_test/dispose_destroy_all_session_test.dart +++ b/test/beans_test/dispose_destroy_all_session_test.dart @@ -1,14 +1,15 @@ -import 'package:dart_ddi/src/exception/bean_not_found.dart'; -import 'package:test/test.dart'; +import 'dart:async'; import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; import '../clazz_samples/a.dart'; import '../clazz_samples/b.dart'; import '../clazz_samples/c.dart'; void disposeDestroyAllSession() { - group('DDI Dispose Destroy ALl Session Tests', () { + group('DDI Dispose Destroy All Session Tests', () { void registerSessionBeans() { DDI.instance.registerSession(() => A(DDI.instance())); DDI.instance.registerSession(() => B(DDI.instance())); @@ -53,5 +54,36 @@ void disposeDestroyAllSession() { expect(() => DDI.instance.get(), throwsA(isA())); expect(() => DDI.instance.get(), throwsA(isA())); }); + + test('Register, get, dispose and destroy Session bean', () async { + DDI.instance.registerSession(() async => A(await DDI.instance())); + DDI.instance + .registerSession>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerSession(C.new); + + final instance1 = await DDI.instance.get>(); + final instance2 = await DDI.instance.get>(); + + expect(instance1, same(instance2)); + expect(instance1.b, same(instance2.b)); + expect(instance1.b.c, same(instance2.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.disposeAllSession(); + + final instance3 = await DDI.instance.get>(); + + expect(false, identical(instance1, instance3)); + expect(false, identical(instance1.b, instance3.b)); + expect(false, identical(instance1.b.c, instance3.b.c)); + expect(instance1.b.c.value, same(instance2.b.c.value)); + + DDI.instance.destroyAllSession(); + + expect(() => DDI.instance.get>(), throwsA(isA())); + expect( + () => DDI.instance.get>(), throwsA(isA())); + expect(() => DDI.instance.get(), throwsA(isA())); + }); }); } diff --git a/test/beans_test/future_post_construct_pre_destroy_test.dart b/test/beans_test/future_post_construct_pre_destroy_test.dart new file mode 100644 index 0000000..83b73ad --- /dev/null +++ b/test/beans_test/future_post_construct_pre_destroy_test.dart @@ -0,0 +1,74 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/l.dart'; + +void futurePostConstructPreDestroyTest() { + group('DDI Future PostConstruct and PreDestroy test', () { + test('Regsiter a Singleton bean with PostConstruct and PreDestroy', + () async { + DDI.instance.registerSingleton( + () => Future.delayed(const Duration(milliseconds: 200), L.new)); + + final L instance = await DDI.instance.get>(); + + expect(instance.value, 'abcd'); + + DDI.instance.destroy>(); + }); + + test('Regsiter a Applcation bean with PostConstruct and PreDestroy', + () async { + DDI.instance.registerApplication( + () => Future.delayed(const Duration(milliseconds: 200), L.new)); + + final L instance = await DDI.instance.get>(); + + expect(instance.value, 'abcd'); + + DDI.instance.destroy>(); + }); + + test('Regsiter a Session bean with PostConstruct and PreDestroy', + () async { + DDI.instance.registerSession( + () => Future.delayed(const Duration(milliseconds: 200), L.new)); + + final L instance = await DDI.instance.get>(); + + expect(instance.value, 'abcd'); + + DDI.instance.destroy>(); + }); + + test('Regsiter a Dependent bean with PostConstruct and PreDestroy', + () async { + DDI.instance.registerDependent( + () => Future.delayed(const Duration(milliseconds: 200), L.new)); + + final L instance = await DDI.instance.get>(); + + expect(instance.value, 'abcd'); + + DDI.instance.destroy>(); + }); + + test('Regsiter a Object bean with PostConstruct and PreDestroy', () async { + Future loadValue() async { + await Future.delayed(const Duration(milliseconds: 200)); + + return L(); + } + + DDI.instance.registerObject(loadValue()); + + final L instance = await DDI.instance.get>(); + + expect(instance.value, 'abcd'); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/get_by_future_type_test.dart b/test/beans_test/get_by_future_type_test.dart new file mode 100644 index 0000000..1d228f4 --- /dev/null +++ b/test/beans_test/get_by_future_type_test.dart @@ -0,0 +1,137 @@ +import 'dart:async'; + +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/g.dart'; +import '../clazz_samples/h.dart'; +import '../clazz_samples/i.dart'; + +void runByFutureType() { + group('DDI Process Future By Type', () { + test('Application Get bean by Type that have registered and dispose', + () async { + ///Where is Singleton, should the register in the correct order + DDI.instance.registerApplication>(() => Future.value(H()), + qualifier: 'firtsClass'); + + final List keys1 = DDI.instance.getByType>(); + + expect(keys1.length, 1); + DDI.instance.registerApplication>(() => Future.value(I()), + qualifier: 'secondClass'); + + final List keys2 = DDI.instance.getByType>(); + + expect(keys2.length, 2); + + final G instance1 = + await DDI.instance.get>(qualifier: keys2[0]); + final G instance2 = + await DDI.instance.get>(qualifier: keys2[1]); + + expect(instance1.area(), instance2.area() / 2); + + DDI.instance.disposeByType>(); + DDI.instance.destroyByType>(); + + expect(() => DDI.instance.get(qualifier: keys2[0]), + throwsA(isA())); + expect(() => DDI.instance.get(qualifier: keys2[1]), + throwsA(isA())); + }); + + test('Dependent Get bean by Type that have registered and dispose', + () async { + DDI.instance + .registerDependent>(() => H(), qualifier: 'firtsClass'); + + final List keys1 = DDI.instance.getByType>(); + + expect(keys1.length, 1); + DDI.instance.registerDependent>(() => Future.value(I()), + qualifier: 'secondClass'); + + final List keys2 = DDI.instance.getByType>(); + + expect(keys2.length, 2); + + final G instance1 = + await DDI.instance.get>(qualifier: keys2[0]); + final G instance2 = + await DDI.instance.get>(qualifier: keys2[1]); + + expect(instance1.area(), instance2.area() / 2); + + DDI.instance.disposeByType>(); + DDI.instance.destroyByType>(); + + expect(() => DDI.instance.get(qualifier: keys2[0]), + throwsA(isA())); + expect(() => DDI.instance.get(qualifier: keys2[1]), + throwsA(isA())); + }); + + test('Session Get bean by Type that have registered and dispose', () async { + DDI.instance + .registerSession>(() => H(), qualifier: 'firtsClass'); + + final List keys1 = DDI.instance.getByType>(); + + expect(keys1.length, 1); + DDI.instance.registerSession>(() => Future.value(I()), + qualifier: 'secondClass'); + + final List keys2 = DDI.instance.getByType>(); + + expect(keys2.length, 2); + + final G instance1 = + await DDI.instance.get>(qualifier: keys2[0]); + final G instance2 = + await DDI.instance.get>(qualifier: keys2[1]); + + expect(instance1.area(), instance2.area() / 2); + + DDI.instance.disposeByType>(); + DDI.instance.destroyByType>(); + + expect(() => DDI.instance.get(qualifier: keys2[0]), + throwsA(isA())); + expect(() => DDI.instance.get(qualifier: keys2[1]), + throwsA(isA())); + }); + + test('Get bean by Type that have registered and dispose', () async { + DDI.instance.registerApplication>( + () => Future.delayed(const Duration(milliseconds: 500), H.new), + qualifier: 'firtsClass'); + + final List keys1 = DDI.instance.getByType>(); + + expect(keys1.length, 1); + DDI.instance + .registerDependent>(I.new, qualifier: 'secondClass'); + + final List keys2 = DDI.instance.getByType>(); + + expect(keys2.length, 2); + + final G instance1 = + await DDI.instance.get>(qualifier: keys2[0]); + final G instance2 = + await DDI.instance.get>(qualifier: keys2[1]); + + expect(instance1.area(), instance2.area() / 2); + + DDI.instance.disposeByType>(); + DDI.instance.destroyByType>(); + + expect(() => DDI.instance.get(qualifier: keys2[0]), + throwsA(isA())); + expect(() => DDI.instance.get(qualifier: keys2[1]), + throwsA(isA())); + }); + }); +} diff --git a/test/beans_test/get_by_type_test.dart b/test/beans_test/get_by_type_test.dart index 80cc1d9..5ef4d18 100644 --- a/test/beans_test/get_by_type_test.dart +++ b/test/beans_test/get_by_type_test.dart @@ -9,7 +9,6 @@ import '../clazz_samples/i.dart'; void runByType() { group('DDI Process By Type', () { test('Application Get bean by Type that have registered and dispose', () { - ///Where is Singleton, should the register in the correct order DDI.instance.registerApplication(() => H(), qualifier: 'firtsClass'); final List keys1 = DDI.instance.getByType(); @@ -36,7 +35,6 @@ void runByType() { }); test('Dependent Get bean by Type that have registered and dispose', () { - ///Where is Singleton, should the register in the correct order DDI.instance.registerDependent(() => H(), qualifier: 'firtsClass'); final List keys1 = DDI.instance.getByType(); @@ -63,7 +61,6 @@ void runByType() { }); test('Session Get bean by Type that have registered and dispose', () { - ///Where is Singleton, should the register in the correct order DDI.instance.registerSession(() => H(), qualifier: 'firtsClass'); final List keys1 = DDI.instance.getByType(); diff --git a/test/beans_test/object_future_test.dart b/test/beans_test/object_future_test.dart index 3c08c91..97fe8b8 100644 --- a/test/beans_test/object_future_test.dart +++ b/test/beans_test/object_future_test.dart @@ -5,10 +5,13 @@ import 'package:test/test.dart'; void objectFuture() { group('DDI Object Future Basic Tests', () { test('Register and retrieve object bean', () async { - DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'futureAuthor'); + DDI.instance.registerObject(Future.value('Willian Marchesan'), + qualifier: 'futureAuthor'); - final instance1 = await DDI.instance.get>(qualifier: 'futureAuthor'); - final instance2 = await DDI.instance.get>(qualifier: 'futureAuthor'); + final instance1 = + await DDI.instance.get>(qualifier: 'futureAuthor'); + final instance2 = + await DDI.instance.get>(qualifier: 'futureAuthor'); expect('Willian Marchesan', instance1); expect(instance1, same(instance2)); @@ -17,13 +20,15 @@ void objectFuture() { }); test('Try to retrieve object bean after removed', () { - DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'futureAuthor'); + DDI.instance.registerObject(Future.value('Willian Marchesan'), + qualifier: 'futureAuthor'); DDI.instance.get(qualifier: 'futureAuthor'); DDI.instance.destroy(qualifier: 'futureAuthor'); - expect(() => DDI.instance.get(qualifier: 'futureAuthor'), throwsA(isA())); + expect(() => DDI.instance.get(qualifier: 'futureAuthor'), + throwsA(isA())); }); test('Try to destroy a undestroyable Object bean', () async { @@ -33,28 +38,34 @@ void objectFuture() { destroyable: false, ); - final instance1 = await DDI.instance.get>(qualifier: 'futureAuthor'); + final instance1 = + await DDI.instance.get>(qualifier: 'futureAuthor'); DDI.instance.destroy(qualifier: 'futureAuthor'); - final String instance2 = await DDI.instance.get(qualifier: 'futureAuthor'); + final String instance2 = + await DDI.instance.get(qualifier: 'futureAuthor'); expect('Willian Marchesan', instance1); expect(instance1, same(instance2)); }); test('Register, retrieve and refresh object bean', () async { - DDI.instance.registerObject(Future.value('Willian Marchesan'), qualifier: 'name'); + DDI.instance + .registerObject(Future.value('Willian Marchesan'), qualifier: 'name'); - final instance1 = await DDI.instance.get>(qualifier: 'name'); - final instance2 = await DDI.instance.get>(qualifier: 'name'); + final instance1 = + await DDI.instance.get>(qualifier: 'name'); + final instance2 = + await DDI.instance.get>(qualifier: 'name'); expect('Willian Marchesan', instance1); expect(instance1, same(instance2)); DDI.instance.refreshObject(Future.value('Will'), qualifier: 'name'); - final String instance3 = await DDI.instance.get>(qualifier: 'name'); + final String instance3 = + await DDI.instance.get>(qualifier: 'name'); expect('Will', instance3); expect(false, identical(instance1, instance3)); diff --git a/test/beans_test/post_construct_pre_destroy_test.dart b/test/beans_test/post_construct_pre_destroy_test.dart index 8a75da1..6437357 100644 --- a/test/beans_test/post_construct_pre_destroy_test.dart +++ b/test/beans_test/post_construct_pre_destroy_test.dart @@ -8,7 +8,9 @@ void postConstructPreDestroyTest() { test('Regsiter a Singleton bean with PostConstruct and PreDestroy', () { DDI.instance.registerSingleton(() => L()); - DDI.instance.get(); + final L instance = DDI.instance.get(); + + expect('abcd', instance.value); DDI.instance.destroy(); }); @@ -16,7 +18,9 @@ void postConstructPreDestroyTest() { test('Regsiter a Applcation bean with PostConstruct and PreDestroy', () { DDI.instance.registerApplication(() => L()); - DDI.instance.get(); + final L instance = DDI.instance.get(); + + expect('abcd', instance.value); DDI.instance.destroy(); }); @@ -24,7 +28,9 @@ void postConstructPreDestroyTest() { test('Regsiter a Session bean with PostConstruct and PreDestroy', () { DDI.instance.registerSession(() => L()); - DDI.instance.get(); + final L instance = DDI.instance.get(); + + expect('abcd', instance.value); DDI.instance.destroy(); }); @@ -32,7 +38,9 @@ void postConstructPreDestroyTest() { test('Regsiter a Dependent bean with PostConstruct and PreDestroy', () { DDI.instance.registerDependent(() => L()); - DDI.instance.get(); + final L instance = DDI.instance.get(); + + expect('abcd', instance.value); DDI.instance.destroy(); }); @@ -40,7 +48,9 @@ void postConstructPreDestroyTest() { test('Regsiter a Object bean with PostConstruct and PreDestroy', () { DDI.instance.registerObject(L()); - DDI.instance.get(); + final L instance = DDI.instance.get(); + + expect('abcd', instance.value); DDI.instance.destroy(); }); diff --git a/test/beans_test/session_future_test.dart b/test/beans_test/session_future_test.dart index 0b73393..c0f1fe1 100644 --- a/test/beans_test/session_future_test.dart +++ b/test/beans_test/session_future_test.dart @@ -13,7 +13,8 @@ void sessionFuture() { group('DDI Session Future Basic Tests', () { void registerSessionBeans() { DDI.instance.registerSession(() async => A(await DDI.instance())); - DDI.instance.registerSession>(() => Future.value(B(DDI.instance()))); + DDI.instance + .registerSession>(() => Future.value(B(DDI.instance()))); DDI.instance.registerSession(C.new); } @@ -52,7 +53,8 @@ void sessionFuture() { removeSessionBeans(); }); - test('Retrieve Session bean after a second "child" bean is diposed', () async { + test('Retrieve Session bean after a second "child" bean is diposed', + () async { registerSessionBeans(); final instance = await DDI.instance.get>(); @@ -68,7 +70,8 @@ void sessionFuture() { removeSessionBeans(); }); - test('Retrieve Session bean after the last "child" bean is diposed', () async { + test('Retrieve Session bean after the last "child" bean is diposed', + () async { registerSessionBeans(); final instance1 = await DDI.instance.get>(); @@ -151,11 +154,13 @@ void sessionFuture() { DDI.instance.destroy(qualifier: 'typeC'); - expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + expect(() => DDI.instance.get(qualifier: 'typeC'), + throwsA(isA())); }); test('Try to destroy a undestroyable Session bean', () { - DDI.instance.registerSession(() => Future.value(SessionDestroyGet()), destroyable: false); + DDI.instance.registerSession(() => Future.value(SessionDestroyGet()), + destroyable: false); final instance1 = DDI.instance.get>(); @@ -209,7 +214,8 @@ void sessionFuture() { DDI.instance.destroy>(); DDI.instance.destroy(); }); - test('Retrieve Session bean after a "child" bean is disposed using Future', () async { + test('Retrieve Session bean after a "child" bean is disposed using Future', + () async { DDI.instance.registerSession(() async => A(await DDI.instance())); DDI.instance.registerSession>(() async => B(DDI.instance())); DDI.instance.registerSession(C.new); diff --git a/test/beans_test/singleton_future_test.dart b/test/beans_test/singleton_future_test.dart index abe3b61..c90b1e6 100644 --- a/test/beans_test/singleton_future_test.dart +++ b/test/beans_test/singleton_future_test.dart @@ -13,7 +13,8 @@ void singletonFuture() { group('DDI Singleton Future Basic Tests', () { void registerSingletonBeans() { DDI.instance.registerApplication(C.new); - DDI.instance.registerApplication>(() => Future.value(B(DDI.instance()))); + DDI.instance.registerApplication>( + () => Future.value(B(DDI.instance()))); DDI.instance.registerApplication(() async => A(await DDI.instance())); } @@ -53,7 +54,8 @@ void singletonFuture() { removeSingletonBeans(); }); - test('Retrieve singleton bean after a second "child" bean is diposed', () async { + test('Retrieve singleton bean after a second "child" bean is diposed', + () async { registerSingletonBeans(); final instance = await DDI.instance.get>(); @@ -79,17 +81,20 @@ void singletonFuture() { }); test('Create, get and remove a qualifier bean', () { - DDI.instance.registerSingleton(() => Future.value(C()), qualifier: 'typeC'); + DDI.instance + .registerSingleton(() => Future.value(C()), qualifier: 'typeC'); DDI.instance.get(qualifier: 'typeC'); DDI.instance.destroy(qualifier: 'typeC'); - expect(() => DDI.instance.get(qualifier: 'typeC'), throwsA(isA())); + expect(() => DDI.instance.get(qualifier: 'typeC'), + throwsA(isA())); }); test('Try to destroy a undestroyable Singleton bean', () { - DDI.instance.registerSingleton(() => Future.value(SingletonDestroyGet()), destroyable: false); + DDI.instance.registerSingleton(() => Future.value(SingletonDestroyGet()), + destroyable: false); final instance1 = DDI.instance.get>(); @@ -128,7 +133,8 @@ void singletonFuture() { test('Register and retrieve Singleton bean using FutureOr', () async { DDI.instance.registerSingleton(C.new); - DDI.instance.registerSingleton>(() async => B(DDI.instance())); + DDI.instance + .registerSingleton>(() async => B(DDI.instance())); DDI.instance.registerSingleton(() async => A(await DDI.instance())); final instance1 = await DDI.instance.get>(); @@ -143,9 +149,12 @@ void singletonFuture() { DDI.instance.destroy>(); DDI.instance.destroy(); }); - test('Retrieve Singleton bean after a "child" bean is disposed using Future', () async { + test( + 'Retrieve Singleton bean after a "child" bean is disposed using Future', + () async { DDI.instance.registerSingleton(C.new); - DDI.instance.registerSingleton>(() async => B(DDI.instance())); + DDI.instance + .registerSingleton>(() async => B(DDI.instance())); DDI.instance.registerSingleton(() async => A(await DDI.instance())); final instance1 = await DDI.instance.get>(); diff --git a/test/clazz_samples/l.dart b/test/clazz_samples/l.dart index 8da9313..97f3a24 100644 --- a/test/clazz_samples/l.dart +++ b/test/clazz_samples/l.dart @@ -6,7 +6,7 @@ class L with PostConstruct, PreDestroy { @override void onPostConstruct() { - print("Do you know how to test"); + value = 'abcd'; } @override diff --git a/test/dart_ddi_test.dart b/test/dart_ddi_test.dart index 7c06912..e1a4bb5 100644 --- a/test/dart_ddi_test.dart +++ b/test/dart_ddi_test.dart @@ -5,6 +5,8 @@ import 'beans_test/circular_injection_test.dart'; import 'beans_test/dependent_future_test.dart'; import 'beans_test/dependent_test.dart'; import 'beans_test/dispose_destroy_all_session_test.dart'; +import 'beans_test/future_post_construct_pre_destroy_test.dart'; +import 'beans_test/get_by_future_type_test.dart'; import 'beans_test/get_by_type_test.dart'; import 'beans_test/interceptor_test.dart'; import 'beans_test/object_future_test.dart'; @@ -38,6 +40,9 @@ void main() { dependentFuture(); objectFuture(); + runByFutureType(); + futurePostConstructPreDestroyTest(); + //Decorators addDecorator(); From ce0cc0377f7529a37ab07490d4fd7a4b7201ebdb Mon Sep 17 00:00:00 2001 From: Willian Marchesan Date: Fri, 26 Jan 2024 23:54:33 -0300 Subject: [PATCH 3/4] Doc: Some Future behaviors fixs --- lib/src/core/bean/dart_ddi.dart | 6 +- lib/src/core/bean/dart_ddi_impl.dart | 6 +- test/beans_test/circular_injection_test.dart | 21 ++- .../beans_test/future_add_decoratos_test.dart | 81 +++++++++++ .../future_circular_injection_test.dart | 132 ++++++++++++++++++ test/dart_ddi_test.dart | 4 + 6 files changed, 240 insertions(+), 10 deletions(-) create mode 100644 test/beans_test/future_add_decoratos_test.dart create mode 100644 test/beans_test/future_circular_injection_test.dart diff --git a/lib/src/core/bean/dart_ddi.dart b/lib/src/core/bean/dart_ddi.dart index c8b505e..57d8ce7 100644 --- a/lib/src/core/bean/dart_ddi.dart +++ b/lib/src/core/bean/dart_ddi.dart @@ -200,7 +200,7 @@ abstract class DDI { /// /// - **Order of Execution:** Decorators are applied in the order they are provided. /// - **Instaces Already Gets:** No changes any Instances that have been get. - void addDecorator( + FutureOr addDecorator( List decorators, {Object? qualifier}); @@ -212,7 +212,7 @@ abstract class DDI { /// - **Around Constructor:** Will not work with Singletons Scope. /// - **Order of Execution:** Interceptor are applied in the order they are provided. /// - **Instaces Already Gets:** No changes any Instances that have been get. - void addInterceptor( + FutureOr addInterceptor( List Function()> interceptors, {Object? qualifier}); @@ -221,7 +221,7 @@ abstract class DDI { /// When using this method, consider the following: /// /// - **Instaces Already Gets:** No changes any Instances that have been get. - void refreshObject( + FutureOr refreshObject( BeanT register, { Object? qualifier, }); diff --git a/lib/src/core/bean/dart_ddi_impl.dart b/lib/src/core/bean/dart_ddi_impl.dart index 3f29c42..9cb8b1b 100644 --- a/lib/src/core/bean/dart_ddi_impl.dart +++ b/lib/src/core/bean/dart_ddi_impl.dart @@ -472,7 +472,7 @@ class _DDIImpl implements DDI { } @override - void addDecorator( + FutureOr addDecorator( List decorators, { Object? qualifier, }) { @@ -512,7 +512,7 @@ class _DDIImpl implements DDI { } @override - void addInterceptor( + FutureOr addInterceptor( List Function()> interceptors, { Object? qualifier, }) { @@ -530,7 +530,7 @@ class _DDIImpl implements DDI { } @override - void refreshObject( + FutureOr refreshObject( BeanT register, { Object? qualifier, }) { diff --git a/test/beans_test/circular_injection_test.dart b/test/beans_test/circular_injection_test.dart index 74f8be9..1663f20 100644 --- a/test/beans_test/circular_injection_test.dart +++ b/test/beans_test/circular_injection_test.dart @@ -19,6 +19,7 @@ void circularDetection() { test('Inject a Application bean depending from a bean that not exists yet', () { + //Work because just Register DDI.instance.registerApplication(() => Father(mother: DDI.instance())); DDI.instance.registerApplication(() => Mother(father: DDI.instance())); @@ -59,40 +60,52 @@ void circularDetection() { test('Get the same Singleton bean 100 times', () { DDI.instance.registerSingleton(() => C()); + int count = 0; for (int i = 0; i < 100; i++) { - DDI.instance(); + count += DDI.instance().value; } + expectLater(count, 100); + DDI.instance.destroy(); }); test('Get the same Application bean 100 times', () { DDI.instance.registerApplication(() => C()); + int count = 0; for (int i = 0; i < 100; i++) { - DDI.instance(); + count += DDI.instance().value; } + expectLater(count, 100); + DDI.instance.destroy(); }); test('Get the same Session bean 100 times', () { DDI.instance.registerSession(() => C()); + int count = 0; for (int i = 0; i < 100; i++) { - DDI.instance(); + count += DDI.instance().value; } + expectLater(count, 100); + DDI.instance.destroy(); }); test('Get the same Dependent bean 100 times', () { DDI.instance.registerDependent(() => C()); + int count = 0; for (int i = 0; i < 100; i++) { - DDI.instance(); + count += DDI.instance().value; } + expectLater(count, 100); + DDI.instance.destroy(); }); }); diff --git a/test/beans_test/future_add_decoratos_test.dart b/test/beans_test/future_add_decoratos_test.dart new file mode 100644 index 0000000..75720f0 --- /dev/null +++ b/test/beans_test/future_add_decoratos_test.dart @@ -0,0 +1,81 @@ +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/d.dart'; +import '../clazz_samples/e.dart'; +import '../clazz_samples/f.dart'; + +void futureAddDecorator() { + group('DDI Future ADD Decorators Tests', () { + Future regraSoma() async { + final instance1 = await DDI.instance.get>(); + + expect(instance1.value, 'bcdfghi'); + + await DDI.instance.addDecorator>([ + (instance) async => E(await instance), + ]); + + final instance2 = await DDI.instance.get>(); + + expect(instance2.value, 'bcdfghdef'); + expect(identical(instance1, instance2), false); + } + + test('ADD Decorators to a Singleton bean', () async { + DDI.instance.registerSingleton>( + () => Future.value(D()), + decorators: [ + (instance) async => E(await instance), + (instance) async => F(await instance), + ], + ); + + await regraSoma(); + + DDI.instance.destroy>(); + }); + + test('ADD Decorators to a Application bean', () async { + DDI.instance.registerApplication>( + () => Future.value(D()), + decorators: [ + (instance) async => E(await instance), + (instance) async => F(await instance), + ], + ); + + await regraSoma(); + + DDI.instance.destroy>(); + }); + + test('ADD Decorators to a Session bean', () async { + DDI.instance.registerSession>( + () => Future.value(D()), + decorators: [ + (instance) async => E(await instance), + (instance) async => F(await instance), + ], + ); + + await regraSoma(); + + DDI.instance.destroy>(); + }); + + test('ADD Decorators to a Dependent bean', () async { + DDI.instance.registerDependent>( + () => Future.value(D()), + decorators: [ + (instance) async => E(await instance), + (instance) async => F(await instance), + ], + ); + + await regraSoma(); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/beans_test/future_circular_injection_test.dart b/test/beans_test/future_circular_injection_test.dart new file mode 100644 index 0000000..38cc0ba --- /dev/null +++ b/test/beans_test/future_circular_injection_test.dart @@ -0,0 +1,132 @@ +import 'package:dart_ddi/dart_ddi.dart'; +import 'package:dart_ddi/src/exception/bean_not_found.dart'; +import 'package:dart_ddi/src/exception/circular_detection.dart'; +import 'package:test/test.dart'; + +import '../clazz_samples/c.dart'; +import '../clazz_samples/father.dart'; +import '../clazz_samples/mother.dart'; + +void futureCircularDetection() { + group('DDI Future Circular Injection Detection tests', () { + test('Inject a Singleton bean depending from a bean that not exists yet', + () { + expectLater( + () => DDI.instance.registerSingleton( + () => Future.value(Father(mother: DDI.instance()))), + throwsA(isA())); + }); + + test('Inject a Application bean depending from a bean that not exists yet', + () { + //Work because just Register + DDI.instance.registerApplication>(() async => + Future.value(Father(mother: await DDI.instance>()))); + DDI.instance.registerApplication>(() async => + Future.value(Mother(father: await DDI.instance>()))); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + }); + + test('Inject a Application bean with circular dependency', () { + DDI.instance.registerApplication>(() async => + Future.value(Father(mother: await DDI.instance>()))); + DDI.instance.registerApplication>(() async => + Future.value(Mother(father: await DDI.instance>()))); + + expectLater(() => DDI.instance>(), + throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + }); + + test('Inject a Dependent bean with circular dependency', () { + DDI.instance.registerDependent>(() async => + Future.value(Father(mother: await DDI.instance>()))); + + DDI.instance.registerDependent>(() async => + Future.value(Mother(father: await DDI.instance>()))); + + expectLater(() => DDI.instance>(), + throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + }); + + test('Inject a Session bean with circular dependency', () { + DDI.instance.registerSession>(() async => + Future.value(Father(mother: await DDI.instance>()))); + + DDI.instance.registerSession>(() async => + Future.value(Mother(father: await DDI.instance>()))); + + expectLater(() => DDI.instance>(), + throwsA(isA())); + + DDI.instance.destroy>(); + DDI.instance.destroy>(); + }); + + test('Get the same Singleton bean 10 times', () async { + DDI.instance.registerSingleton(() => Future.value(C())); + + int count = 0; + for (int i = 0; i < 10; i++) { + final C val = await DDI.instance>(); + count += val.value; + } + + expectLater(count, 10); + + DDI.instance.destroy>(); + }); + + test('Get the same Application bean 10 times', () async { + DDI.instance.registerApplication(() => Future.value(C())); + + int count = 0; + for (int i = 0; i < 10; i++) { + final C val = await DDI.instance>(); + count += val.value; + } + + expectLater(count, 10); + + DDI.instance.destroy>(); + }); + + test('Get the same Session bean 10 times', () async { + DDI.instance.registerSession(() async { + await Future.delayed(const Duration(milliseconds: 200)); + return Future.value(C()); + }); + + int count = 0; + for (int i = 0; i < 10; i++) { + final C val = await DDI.instance>(); + count += val.value; + } + + expectLater(count, 10); + + DDI.instance.destroy>(); + }); + + test('Get the same Dependent bean 10 times', () async { + DDI.instance.registerDependent(() => Future.value(C())); + + int count = 0; + for (int i = 0; i < 10; i++) { + final C val = await DDI.instance>(); + count += val.value; + } + + expectLater(count, 10); + + DDI.instance.destroy>(); + }); + }); +} diff --git a/test/dart_ddi_test.dart b/test/dart_ddi_test.dart index e1a4bb5..a5a45f2 100644 --- a/test/dart_ddi_test.dart +++ b/test/dart_ddi_test.dart @@ -5,6 +5,8 @@ import 'beans_test/circular_injection_test.dart'; import 'beans_test/dependent_future_test.dart'; import 'beans_test/dependent_test.dart'; import 'beans_test/dispose_destroy_all_session_test.dart'; +import 'beans_test/future_add_decoratos_test.dart'; +import 'beans_test/future_circular_injection_test.dart'; import 'beans_test/future_post_construct_pre_destroy_test.dart'; import 'beans_test/get_by_future_type_test.dart'; import 'beans_test/get_by_type_test.dart'; @@ -45,12 +47,14 @@ void main() { //Decorators addDecorator(); + futureAddDecorator(); //Interceptor interceptor(); //CircularDetection circularDetection(); + futureCircularDetection(); //Events eventTest(); From b57546f69ce6367decfbd87c377f7f159ef6d2fd Mon Sep 17 00:00:00 2001 From: Willian Marchesan Date: Sat, 27 Jan 2024 00:11:00 -0300 Subject: [PATCH 4/4] Doc: Version 0.3.1 --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e2b0f..e5b9855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.3.1 + +* Fixed Documentation links. +* Some Futures instances behaviors fix. + ## 0.3.0 * Migrating from flutter_test and flutter_lints to test and lints. diff --git a/pubspec.yaml b/pubspec.yaml index 036d4c5..5e7d8b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: dart_ddi description: "A Dependency Injection package, with Qualifier, Decorators, Interceptors, Events and more. Inspired by Java CDI and get_it." -version: 0.3.0 +version: 0.3.1 homepage: https://github.com/Willian199/dart_ddi environment: