diff --git a/cherrypick/test/src/scope_test.dart b/cherrypick/test/src/scope_test.dart index 267cac8..ed1d866 100644 --- a/cherrypick/test/src/scope_test.dart +++ b/cherrypick/test/src/scope_test.dart @@ -73,6 +73,120 @@ void main() { expect(() => scope.resolve(), throwsA(isA())); }); }); + + group('Named dependencies', () { + test('Resolve named binding', () { + final scope = Scope(null) + ..installModules([ + TestModule(value: "first"), + TestModule(value: "second", name: "special") + ]); + expect(scope.resolve(named: "special"), "second"); + expect(scope.resolve(), "first"); + }); + + test('Named binding does not clash with unnamed', () { + final scope = Scope(null) + ..installModules([ + TestModule(value: "foo", name: "bar"), + ]); + expect(() => scope.resolve(), throwsA(isA())); + expect(scope.resolve(named: "bar"), "foo"); + }); + + test("tryResolve returns null for missing named", () { + final scope = Scope(null) + ..installModules([ + TestModule(value: "foo"), + ]); + expect(scope.tryResolve(named: "bar"), isNull); + }); + }); + + group('Provider with params', () { + test('Resolve dependency using providerWithParams', () { + final scope = Scope(null) + ..installModules([ + _InlineModule((m, s) { + m.bind().toProvideWithParams((param) => (param as int) * 2); + }), + ]); + expect(scope.resolve(params: 3), 6); + expect( + () => scope.resolve(), + throwsA(isA()), + ); + }); + }); + + group('Async resolution', () { + test('Resolve async instance', () async { + final scope = Scope(null) + ..installModules([ + _InlineModule((m, s) { + m.bind().toInstanceAsync(Future.value('async value')); + }), + ]); + expect(await scope.resolveAsync(), "async value"); + }); + + test('Resolve async provider', () async { + final scope = Scope(null) + ..installModules([ + _InlineModule((m, s) { + m.bind().toProvideAsync(() async => 7); + }), + ]); + expect(await scope.resolveAsync(), 7); + }); + + test('Resolve async provider with param', () async { + final scope = Scope(null) + ..installModules([ + _InlineModule((m, s) { + m.bind().toProvideAsyncWithParams((x) async => (x as int) * 3); + }), + ]); + expect(await scope.resolveAsync(params: 2), 6); + expect( + () => scope.resolveAsync(), + throwsA(isA()), + ); + }); + + test('tryResolveAsync returns null for missing', () async { + final scope = Scope(null); + final result = await scope.tryResolveAsync(); + expect(result, isNull); + }); + }); + + group("Drop modules", () { + test("After dropModules resolves fail", () { + final scope = Scope(null)..installModules([TestModule(value: 5)]); + expect(scope.resolve(), 5); + scope.dropModules(); + expect(() => scope.resolve(), throwsA(isA())); + }); + }); + + group("Subscope closing", () { + test("closeSubScope removes subscope", () { + final scope = Scope(null); + final subScope = scope.openSubScope("child"); + expect(scope.openSubScope("child"), same(subScope)); + scope.closeSubScope("child"); + final newSubScope = scope.openSubScope("child"); + expect(newSubScope, isNot(same(subScope))); // New instance after close + }); + }); + + group("tryResolve returns null if not found", () { + test("Returns null for missing dependency", () { + final scope = Scope(null); + expect(scope.tryResolve(), isNull); + }); + }); } class TestModule extends Module { @@ -89,3 +203,12 @@ class TestModule extends Module { } } } + +/// Вспомогательный модуль для подстановки builder'а через конструктор +class _InlineModule extends Module { + final void Function(Module, Scope) _builder; + _InlineModule(this._builder); + + @override + void builder(Scope s) => _builder(this, s); +}