import 'package:dart_di/di_container.dart'; import 'package:dart_di/resolvers/resolver.dart'; import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; void main() { group('Without parent', () { test('Container bind throws state error if it\'s already has resolver', () { final container = new DiContainer(); container.bind().toResolver(_makeResolver(5)); expect(() => container.bind().toResolver(_makeResolver(3)), throwsA(isA())); }); test("Container resolves value after adding a dependency", () { final expectedValue = 3; final container = new DiContainer(); container.bind().toResolver(_makeResolver(expectedValue)); expect(container.resolve(), expectedValue); }); test("Container throws state error if the value can't be resolved", () { final container = DiContainer(); expect(() => container.resolve(), throwsA(isA())); }); test("Container has() returns true if it has resolver", () { final expectedValue = 5; final container = new DiContainer(); container.bind().toResolver(_makeResolver(expectedValue)); expect(container.has(), true); }); test("Container has() returns false if it hasn't resolver", () { final container = new DiContainer(); expect(container.has(), false); }); test("Container hasInTree() returns true if it has resolver", () { final expectedValue = 5; final container = DiContainer(); container.bind().toResolver(_makeResolver(expectedValue)); expect(container.hasInTree(), true); }); test("Container hasInTree() returns true if it hasn`t resolver", () { final container = DiContainer(); expect(container.hasInTree(), false); }); }); group('With parent', () { test( "Container bind() throws state error (if it's parent already has a resolver)", () { final parentContainer = new DiContainer(); final container = new DiContainer(parentContainer); parentContainer.bind().toResolver(_makeResolver(5)); expect(() => container.bind().toResolver(_makeResolver(3)), throwsA(isA())); }); test("Container resolve() returns a value from parent container", () { final expectedValue = 5; final parentContainer = DiContainer(); final container = DiContainer(parentContainer); parentContainer.bind().toResolver(_makeResolver(expectedValue)); expect(container.resolve(), expectedValue); }); }); test("Container resolve() returns a several value from parent container", () { final expectedIntValue = 5; final expectedStringValue = "Hello world"; final parentContainer = DiContainer(); final container = DiContainer(parentContainer); parentContainer.bind().toResolver(_makeResolver(expectedIntValue)); parentContainer .bind() .toResolver(_makeResolver(expectedStringValue)); expect(container.resolve(), expectedIntValue); expect(container.resolve(), expectedStringValue); }); test("Container resolve() throws a state error if parent hasn't value too", () { final parentContainer = DiContainer(); final container = DiContainer(parentContainer); expect(() => container.resolve(), throwsA(isA())); }); test("Container has() returns false if parent has a resolver", () { final parentContainer = DiContainer(); final container = DiContainer(parentContainer); parentContainer.bind().toResolver(_makeResolver(5)); expect(container.has(), false); }); test("Container has() returns false if parent hasn't a resolver", () { final parentContainer = DiContainer(); final container = DiContainer(parentContainer); expect(container.has(), false); }); test("Container hasInTree() returns true if parent has a resolver", () { final parentContainer = DiContainer(); final container = DiContainer(parentContainer); parentContainer.bind().toResolver(_makeResolver(5)); expect(container.hasInTree(), true); }); test("Test asSingelton", () { final expectedIntValue = 10; final containerA = DiContainer(); final containerB = DiContainer(containerA); containerA.bind().toValue(expectedIntValue).asSingleton(); expect(containerB.resolve(), expectedIntValue); }); test("Bind to the factory resolves with value", () { final container = DiContainer(); final a = AA(); container.bind().toFactory(() => a); expect(container.resolve(), a); }); test("Bind to the factory resolves with value", () { final container = DiContainer(); final a = AA(); container.bind().toValue(a); container.bind().toFactory1((a) => DependOnA(a)); expect(container.resolve().a, a); }); test("Bind to the factory resolves with 2 value", () { final container = DiContainer(); final a = AA(); final b = BB(); container.bind().toValue(a); container.bind().toValue(b); container.bind().toFactory2((a, b) => DependOnAB(a, b)); expect(container.resolve().a, a); expect(container.resolve().b, b); }); test("Bind to the factory resolves with 3 value", () { final container = DiContainer(); final a = AA(); final b = BB(); final c = CC(); container.bind().toValue(a); container.bind().toValue(b); container.bind().toValue(c); container .bind() .toFactory3((a, b, c) => DependOnABC(a, b, c)); expect(container.resolve().a, a); expect(container.resolve().b, b); expect(container.resolve().c, c); }); } ResolverMock _makeResolver(T expectedValue) { final resolverMock = new ResolverMock(); when(resolverMock.resolve()).thenReturn(expectedValue); return resolverMock; } class ResolverMock extends Mock implements Resolver {} abstract class A {} class AA implements A {} abstract class B {} class BB implements B {} abstract class C {} class CC implements C {} class DependOnA { final A a; DependOnA(this.a) : assert(a != null); } class DependOnAB { final A a; final B b; DependOnAB(this.a, this.b) : assert(a != null && b != null); } class DependOnABC { final A a; final B b; final C c; DependOnABC(this.a, this.b, this.c) : assert(a != null && b != null && c != null); }