add: adding container to platform

This commit is contained in:
Patrick Stewart 2024-11-28 16:09:46 -07:00
parent 933321f13f
commit 6ff734bdf7
14 changed files with 2985 additions and 0 deletions

View file

@ -0,0 +1,126 @@
# Laravel Container Examples
These examples demonstrate how to use the Laravel-style dependency injection container in Dart.
## Basic Container Features (container_usage.dart)
Shows core container features using a payment processing example:
```dart
// Basic binding
container.bind<PaymentGateway>((c) => StripeGateway(c.make<String>()));
// Singleton registration
container.singleton<PaymentService>((c) => PaymentService(c.make<PaymentGateway>()));
// Contextual binding
container.when(PaymentService)
.needs<PaymentGateway>()
.give(PayPalGateway());
// Tagged services
container.tag([StripeGateway, PayPalGateway], 'gateways');
final gateways = container.tagged<PaymentGateway>('gateways');
// Instance extending
container.extend(PaymentGateway, (gateway) {
print('Payment gateway was created');
});
```
Run with:
```bash
dart run container_usage.dart
```
## Advanced Container Features (advanced_usage.dart)
Demonstrates advanced container capabilities:
```dart
// Child containers
final rootContainer = IlluminateContainer(reflector);
rootContainer.singleton<Logger>((c) => ProductionLogger());
final testContainer = rootContainer.createChild();
testContainer.singleton<Logger>((c) => TestLogger());
// Scoped bindings
container.scoped<RequestScope>((c) => RequestScope());
container.bind<UserRepository>((c) => UserRepository(
c.make<Logger>(),
c.make<RequestScope>()
));
// Scope lifecycle
final repo1 = container.make<UserRepository>();
final repo2 = container.make<UserRepository>();
assert(identical(repo1.scope, repo2.scope)); // Same scope
container.forgetScopedInstances(); // Clear scope
final repo3 = container.make<UserRepository>();
assert(!identical(repo1.scope, repo3.scope)); // New scope
```
Run with:
```bash
dart run advanced_usage.dart
```
## Application Architecture (app_example.dart)
Shows how to use the container in a real application:
```dart
// Register repositories
container.singleton<UserRepository>((c) => DatabaseUserRepository());
// Register services
container.singleton<EmailService>((c) => EmailService());
container.singleton<UserService>((c) => UserService(
c.make<UserRepository>(),
c.make<EmailService>()
));
// Register controllers
container.singleton<UserController>((c) => UserController(
c.make<UserService>()
));
// Use the application
final controller = container.make<UserController>();
controller.createUser('John Doe', 'john@example.com');
```
Run with:
```bash
dart run app_example.dart
```
## Key Features Demonstrated
1. Dependency Registration
- Basic bindings
- Singleton registration
- Factory bindings
- Instance registration
- Scoped bindings
2. Service Resolution
- Automatic dependency injection
- Contextual binding
- Tagged services
- Instance extending
3. Container Features
- Child containers
- Scope management
- Service location
- Interface binding
4. Architecture Patterns
- Repository pattern
- Service layer
- Dependency injection
- Interface segregation

View file

@ -0,0 +1,111 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
// Example services
abstract class Logger {
void log(String message);
}
class ProductionLogger implements Logger {
@override
void log(String message) => print('PROD: $message');
}
class TestLogger implements Logger {
@override
void log(String message) => print('TEST: $message');
}
class RequestScope {
final String id = DateTime.now().toIso8601String();
@override
String toString() => 'RequestScope($id)';
}
class UserRepository {
final Logger logger;
final RequestScope scope;
UserRepository(this.logger, this.scope);
void save(String userId) {
logger.log('[${scope.id}] Saving user: $userId');
}
}
void main() {
// Create root container
final container = IlluminateContainer(ExampleReflector());
print('1. Child Containers');
print('------------------');
// Register production logger in root
container.singleton<Logger>((c) => ProductionLogger());
// Create child container with test logger
final testContainer = container.createChild();
testContainer.singleton<Logger>((c) => TestLogger());
// Use both containers
container.make<Logger>().log('Using production logger');
testContainer.make<Logger>().log('Using test logger');
container.make<Logger>().log('Still using production logger');
print('\n2. Scoped Bindings');
print('-----------------');
// Register scoped request
container.scoped<RequestScope>((c) {
final scope = RequestScope();
print('Created new scope: $scope');
return scope;
});
// Register repository that uses scope
container.bind<UserRepository>(
(c) => UserRepository(c.make<Logger>(), c.make<RequestScope>()));
print('\nFirst request:');
// Same scope within request
final repo1 = container.make<UserRepository>();
final repo2 = container.make<UserRepository>();
repo1.save('user1');
repo2.save('user2');
// Verify same scope
print('Using same scope: ${identical(repo1.scope, repo2.scope)}');
print('\nNew request:');
// Clear scope
container.forgetScopedInstances();
// New scope for new request
final repo3 = container.make<UserRepository>();
repo3.save('user3');
// Verify different scope
print('Using different scope: ${!identical(repo1.scope, repo3.scope)}');
}
/// Example reflector implementation
class ExampleReflector implements ReflectorContract {
@override
String? getName(Symbol symbol) => null;
@override
ReflectedClassContract? reflectClass(Type clazz) => null;
@override
ReflectedFunctionContract? reflectFunction(Function function) => null;
@override
ReflectedInstanceContract? reflectInstance(Object object) => null;
@override
ReflectedTypeContract reflectFutureOf(Type type) {
throw UnsupportedError('Future reflection not needed for example');
}
@override
ReflectedTypeContract? reflectType(Type type) => null;
}

View file

@ -0,0 +1,134 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
// Domain Models
class User {
final String id;
final String name;
final String email;
User(this.id, this.name, this.email);
}
// Repository Layer
abstract class UserRepository {
User? findById(String id);
void save(User user);
}
class DatabaseUserRepository implements UserRepository {
final Map<String, User> _users = {};
@override
User? findById(String id) => _users[id];
@override
void save(User user) {
print('DB: Saving user ${user.id}');
_users[user.id] = user;
}
}
// Service Layer
class UserService {
final UserRepository repository;
final EmailService emailService;
UserService(this.repository, this.emailService);
void registerUser(String name, String email) {
// Create user
final user =
User(DateTime.now().millisecondsSinceEpoch.toString(), name, email);
// Save user
repository.save(user);
// Send welcome email
emailService.sendWelcomeEmail(user);
}
User? getUser(String id) => repository.findById(id);
}
class EmailService {
void sendWelcomeEmail(User user) {
print('Sending welcome email to ${user.email}');
}
}
// Controller Layer
class UserController {
final UserService userService;
UserController(this.userService);
void createUser(String name, String email) {
try {
userService.registerUser(name, email);
print('User created successfully');
} catch (e) {
print('Error creating user: $e');
}
}
void getUser(String id) {
final user = userService.getUser(id);
if (user != null) {
print('Found user: ${user.name} (${user.email})');
} else {
print('User not found');
}
}
}
void main() {
// Create container
final container = IlluminateContainer(ExampleReflector());
// Register repositories
container.singleton<UserRepository>((c) => DatabaseUserRepository());
// Register services
container.singleton<EmailService>((c) => EmailService());
container.singleton<UserService>(
(c) => UserService(c.make<UserRepository>(), c.make<EmailService>()));
// Register controllers
container
.singleton<UserController>((c) => UserController(c.make<UserService>()));
// Use the application
final controller = container.make<UserController>();
// Create a user
print('Creating user...');
controller.createUser('John Doe', 'john@example.com');
// Try to find the user
print('\nLooking up user...');
controller.getUser('123'); // Not found
}
/// Example reflector implementation
class ExampleReflector implements ReflectorContract {
@override
String? getName(Symbol symbol) => null;
@override
ReflectedClassContract? reflectClass(Type clazz) => null;
@override
ReflectedFunctionContract? reflectFunction(Function function) => null;
@override
ReflectedInstanceContract? reflectInstance(Object object) => null;
@override
ReflectedTypeContract reflectFutureOf(Type type) {
throw UnsupportedError('Future reflection not needed for example');
}
@override
ReflectedTypeContract? reflectType(Type type) => null;
}

View file

@ -0,0 +1,120 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
// Example services
abstract class PaymentGateway {
void processPayment(double amount);
}
class StripeGateway implements PaymentGateway {
final String apiKey;
StripeGateway(this.apiKey);
@override
void processPayment(double amount) {
print('Stripe: Processing \$$amount');
}
}
class PayPalGateway implements PaymentGateway {
@override
void processPayment(double amount) {
print('PayPal: Processing \$$amount');
}
}
class PaymentService {
final PaymentGateway gateway;
PaymentService(this.gateway);
void pay(double amount) {
print('Payment requested');
gateway.processPayment(amount);
}
}
void main() {
// Create container
final container = IlluminateContainer(ExampleReflector());
print('1. Basic Binding');
// Register API key
container.instance<String>('stripe-key-123');
// Register payment gateway
container.bind<PaymentGateway>((c) => StripeGateway(c.make<String>()));
// Use the gateway
final gateway = container.make<PaymentGateway>();
gateway.processPayment(99.99);
print('\n2. Singleton');
// Register payment service as singleton
container.singleton<PaymentService>(
(c) => PaymentService(c.make<PaymentGateway>()));
// Get same instance twice
final service1 = container.make<PaymentService>();
final service2 = container.make<PaymentService>();
print('Same instance: ${identical(service1, service2)}');
print('\n3. Contextual Binding');
// Use PayPal for specific service
container.when(PaymentService).needs<PaymentGateway>().give(PayPalGateway());
// New service uses PayPal
final paypalService = container.make<PaymentService>();
paypalService.pay(49.99);
print('\n4. Tagged Services');
// Register concrete implementations
container.bind<StripeGateway>((c) => StripeGateway(c.make<String>()));
container.bind<PayPalGateway>((c) => PayPalGateway());
// Tag payment gateways
container.tag([StripeGateway, PayPalGateway], 'gateways');
// Get all gateways
final gateways = container.tagged<PaymentGateway>('gateways');
print('Found ${gateways.length} payment gateways');
// Use each gateway
for (final gateway in gateways) {
gateway.processPayment(29.99);
}
print('\n5. Extending Instances');
// Add logging to payment gateway
container.extend(PaymentGateway, (gateway) {
print('Payment gateway was created');
});
// Extension runs when making instance
final extendedGateway = container.make<PaymentGateway>();
extendedGateway.processPayment(199.99);
}
/// Example reflector implementation
class ExampleReflector implements ReflectorContract {
@override
String? getName(Symbol symbol) => null;
@override
ReflectedClassContract? reflectClass(Type clazz) => null;
@override
ReflectedFunctionContract? reflectFunction(Function function) => null;
@override
ReflectedInstanceContract? reflectInstance(Object object) => null;
@override
ReflectedTypeContract reflectFutureOf(Type type) {
throw UnsupportedError('Future reflection not needed for example');
}
@override
ReflectedTypeContract? reflectType(Type type) => null;
}

View file

@ -0,0 +1,3 @@
library platform_container;
export 'src/container.dart';

View file

@ -0,0 +1,461 @@
import 'package:platform_contracts/contracts.dart';
/// Laravel-style container implementation.
class IlluminateContainer implements ContainerContract {
final ReflectorContract _reflector;
final Map<Type, dynamic Function(ContainerContract)> _bindings = {};
final Map<Type, dynamic> _instances = {};
final Map<String, dynamic> _namedInstances = {};
final Map<String, List<Type>> _tags = {};
final Map<Type, Map<Type, dynamic>> _contextualBindings = {};
final Map<String, Function> _methodBindings = {};
final Map<Type, Type> _aliases = {};
final Map<Type, List<Function>> _extenders = {};
final Map<Type, List<Function>> _reboundCallbacks = {};
final Map<Type, dynamic> _scopedInstances = {};
final IlluminateContainer? _parent;
final List<Function> _beforeResolvingCallbacks = [];
final List<Function> _resolvingCallbacks = [];
final List<Function> _afterResolvingCallbacks = [];
IlluminateContainer(this._reflector) : _parent = null;
IlluminateContainer._child(this._parent, this._reflector);
@override
ReflectorContract get reflector => _reflector;
@override
bool get isRoot => _parent == null;
@override
ContainerContract createChild() {
return IlluminateContainer._child(this, _reflector);
}
@override
bool bound(String abstract) {
return has(Type);
}
@override
void bind<T>(T Function(ContainerContract) concrete, {bool shared = false}) {
if (shared) {
singleton<T>(concrete);
} else {
registerFactory<T>(concrete);
}
}
@override
void bindIf<T>(T Function(ContainerContract) concrete,
{bool shared = false}) {
if (!has<T>()) {
bind<T>(concrete, shared: shared);
}
}
@override
void singleton<T>(T Function(ContainerContract) concrete) {
registerLazySingleton<T>(concrete);
}
@override
void singletonIf<T>(T Function(ContainerContract) concrete) {
if (!has<T>()) {
singleton<T>(concrete);
}
}
@override
void scoped<T>(T Function(ContainerContract) concrete) {
final type = T;
T Function(ContainerContract) wrapper = (container) {
if (!_scopedInstances.containsKey(type)) {
_scopedInstances[type] = concrete(container);
}
return _scopedInstances[type] as T;
};
_bindings[type] = wrapper;
}
@override
void scopedIf<T>(T Function(ContainerContract) concrete) {
if (!has<T>()) {
scoped<T>(concrete);
}
}
@override
T instance<T>(T instance) {
return registerSingleton<T>(instance);
}
@override
void bindMethod(String method, Function callback) {
_methodBindings[method] = callback;
}
@override
dynamic call(Function callback, [List<dynamic> parameters = const []]) {
final reflected = reflector.reflectFunction(callback);
if (reflected == null) {
Function.apply(callback, parameters);
return null;
}
final injectedParams = reflected.parameters.map((param) {
if (parameters.isNotEmpty) {
return parameters.removeAt(0);
}
return make(param.type.reflectedType);
}).toList();
final result = Function.apply(callback, injectedParams);
return result ?? null;
}
@override
Function wrap(Function callback, [List<dynamic> parameters = const []]) {
return () => call(callback, parameters);
}
@override
ContextualBindingBuilder when(Type concrete) {
return _ContextualBindingBuilder(this, concrete);
}
@override
void addContextualBinding(
Type concrete, Type abstract, dynamic implementation) {
_contextualBindings.putIfAbsent(concrete, () => {})[abstract] =
implementation;
}
@override
void beforeResolving<T>(
void Function(ContainerContract, T instance) callback) {
_beforeResolvingCallbacks.add(callback);
}
@override
void resolving<T>(void Function(ContainerContract, T instance) callback) {
_resolvingCallbacks.add(callback);
}
@override
void afterResolving<T>(
void Function(ContainerContract, T instance) callback) {
_afterResolvingCallbacks.add(callback);
}
@override
bool has<T>([Type? t]) {
final type = t ?? T;
return _bindings.containsKey(type) ||
_instances.containsKey(type) ||
(_parent?.has<T>(t) ?? false);
}
@override
bool hasNamed(String name) {
return _namedInstances.containsKey(name) ||
(_parent?.hasNamed(name) ?? false);
}
@override
T make<T>([Type? type]) {
final resolveType = type ?? T;
final concrete = _aliases[resolveType] ?? resolveType;
// Fire before resolving callbacks
_fireBeforeResolvingCallbacks<T>(null);
// Check for singleton instance
if (_instances.containsKey(concrete)) {
final instance = _instances[concrete];
// Apply extenders to singleton instance
final extenders = getExtenders(concrete);
for (var extender in extenders) {
extender(instance);
}
_fireResolvingCallbacks<T>(instance as T);
return instance as T;
}
// Check for contextual binding
if (_contextualBindings.containsKey(concrete)) {
final bindings = _contextualBindings[concrete]!;
if (bindings.containsKey(T)) {
final binding = bindings[T];
if (binding is Function) {
final instance = binding(this) as T;
// Apply extenders to contextual binding instance
final extenders = getExtenders(concrete);
for (var extender in extenders) {
extender(instance);
}
_fireResolvingCallbacks<T>(instance);
return instance;
}
_fireResolvingCallbacks<T>(binding as T);
return binding as T;
}
}
// Check for binding
if (_bindings.containsKey(concrete)) {
final instance = _bindings[concrete]!(this);
// Apply extenders to factory instance
final extenders = getExtenders(concrete);
for (var extender in extenders) {
extender(instance);
}
_fireResolvingCallbacks<T>(instance as T);
return instance as T;
}
// Check parent container
if (_parent != null && _parent!.has<T>(type)) {
return _parent!.make<T>(type);
}
// Try to create instance via reflection
final reflected = reflector.reflectClass(concrete);
if (reflected == null) {
throw StateError('Could not reflect type $concrete');
}
try {
final instance = reflected.newInstance('', []).reflectee as T;
// Apply extenders to reflected instance
final extenders = getExtenders(concrete);
for (var extender in extenders) {
extender(instance);
}
_fireResolvingCallbacks<T>(instance);
return instance;
} catch (e) {
throw StateError(
'Failed to create instance of $concrete: ${e.toString()}');
}
}
void _fireBeforeResolvingCallbacks<T>(T? instance) {
for (var callback in _beforeResolvingCallbacks) {
callback(this, instance);
}
}
void _fireResolvingCallbacks<T>(T instance) {
for (var callback in _resolvingCallbacks) {
callback(this, instance);
}
for (var callback in _afterResolvingCallbacks) {
callback(this, instance);
}
}
@override
Future<T> makeAsync<T>([Type? type]) async {
try {
final instance = make<T>(type);
if (instance is Future<T>) {
return instance;
}
return Future<T>.value(instance);
} catch (e) {
final futureType = reflector.reflectFutureOf(type ?? T);
final instance = futureType.newInstance('', []);
if (instance.reflectee is Future<T>) {
return instance.reflectee as Future<T>;
}
throw StateError('Failed to create Future<$T>: Invalid instance type');
}
}
@override
T registerSingleton<T>(T object, {Type? as}) {
final type = as ?? T;
if (_instances.containsKey(type)) {
throw StateError('Singleton already registered for type $type');
}
_instances[type] = object;
return object;
}
@override
T Function(ContainerContract) registerFactory<T>(
T Function(ContainerContract) factory,
{Type? as}) {
final type = as ?? T;
_bindings[type] = factory;
return factory;
}
@override
T Function(ContainerContract) registerLazySingleton<T>(
T Function(ContainerContract) factory,
{Type? as}) {
final type = as ?? T;
T Function(ContainerContract) wrapper = (container) {
if (!_instances.containsKey(type)) {
_instances[type] = factory(container);
}
return _instances[type] as T;
};
_bindings[type] = wrapper;
return wrapper;
}
@override
T findByName<T>(String name) {
if (_namedInstances.containsKey(name)) {
return _namedInstances[name] as T;
}
if (_parent != null) {
return _parent!.findByName<T>(name);
}
throw StateError('No singleton registered with name "$name"');
}
@override
T registerNamedSingleton<T>(String name, T object) {
if (_namedInstances.containsKey(name)) {
throw StateError('Singleton already registered with name "$name"');
}
_namedInstances[name] = object;
return object;
}
@override
void tag(List<Type> abstracts, String tag) {
_tags.putIfAbsent(tag, () => []).addAll(abstracts);
}
@override
List<T> tagged<T>(String tag) {
final types = _tags[tag] ?? [];
if (types.isEmpty) {
throw StateError('No types registered for tag "$tag"');
}
final instances = <T>[];
for (final type in types) {
if (_bindings.containsKey(type)) {
final instance = _bindings[type]!(this) as T;
instances.add(instance);
} else if (_parent != null && _parent!.has(type)) {
final instance = _parent!.make(type) as T;
instances.add(instance);
} else {
throw StateError('Could not resolve type $type');
}
}
return instances;
}
@override
void alias(Type abstract, Type alias) {
if (abstract == alias) {
throw StateError('$abstract is aliased to itself.');
}
_aliases[alias] = abstract;
}
@override
bool isAlias(String name) {
return _aliases.keys.any((type) => type.toString() == name);
}
@override
Type getAlias(Type abstract) {
return _aliases[abstract] ?? abstract;
}
@override
void extend(Type abstract, Function(dynamic instance) extension) {
_extenders.putIfAbsent(abstract, () => []).add(extension);
}
@override
List<Function> getExtenders(Type abstract) {
return _extenders[abstract] ?? [];
}
@override
void forgetExtenders(Type abstract) {
_extenders.remove(abstract);
}
@override
void forgetInstance(Type abstract) {
_instances.remove(abstract);
}
@override
void forgetInstances() {
_instances.clear();
}
@override
void forgetScopedInstances() {
_scopedInstances.clear();
}
@override
void flush() {
_bindings.clear();
_instances.clear();
_namedInstances.clear();
_tags.clear();
_contextualBindings.clear();
_methodBindings.clear();
_aliases.clear();
_extenders.clear();
_reboundCallbacks.clear();
_scopedInstances.clear();
_beforeResolvingCallbacks.clear();
_resolvingCallbacks.clear();
_afterResolvingCallbacks.clear();
}
@override
void rebinding(Type abstract, Function(ContainerContract, dynamic) callback) {
_reboundCallbacks.putIfAbsent(abstract, () => []).add(callback);
}
@override
void refresh(Type abstract, dynamic target, String method) {
final instance = make(abstract);
for (var callback in _reboundCallbacks[abstract] ?? []) {
callback(this, instance);
}
Function.apply(target[method], [instance]);
}
}
class _ContextualBindingBuilder implements ContextualBindingBuilder {
final IlluminateContainer _container;
final Type _concrete;
Type? _needsType;
_ContextualBindingBuilder(this._container, this._concrete);
@override
ContextualBindingBuilder needs<T>() {
_needsType = T;
return this;
}
@override
void give(dynamic implementation) {
if (_needsType == null) {
throw StateError('Must call needs() before give()');
}
_container.addContextualBinding(_concrete, _needsType!, implementation);
}
}

View file

@ -0,0 +1,561 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
url: "https://pub.dev"
source: hosted
version: "73.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
url: "https://pub.dev"
source: hosted
version: "6.8.0"
args:
dependency: transitive
description:
name: args
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
url: "https://pub.dev"
source: hosted
version: "2.6.0"
async:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
version: "2.12.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
build:
dependency: transitive
description:
name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
build_config:
dependency: transitive
description:
name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
url: "https://pub.dev"
source: hosted
version: "1.1.1"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
url: "https://pub.dev"
source: hosted
version: "2.4.13"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
url: "https://pub.dev"
source: hosted
version: "7.3.2"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
url: "https://pub.dev"
source: hosted
version: "8.9.2"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
url: "https://pub.dev"
source: hosted
version: "4.10.1"
collection:
dependency: "direct main"
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev"
source: hosted
version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
url: "https://pub.dev"
source: hosted
version: "2.3.7"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.dev"
source: hosted
version: "1.1.1"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
graphs:
dependency: transitive
description:
name: graphs
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
lints:
dependency: "direct dev"
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev"
source: hosted
version: "1.3.0"
macros:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16+1"
meta:
dependency: "direct main"
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.16.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
mockito:
dependency: "direct dev"
description:
name: mockito
sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
url: "https://pub.dev"
source: hosted
version: "5.4.4"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
platform_contracts:
dependency: "direct main"
description:
path: "../contracts"
relative: true
source: path
version: "1.0.0"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
url: "https://pub.dev"
source: hosted
version: "1.3.0"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
url: "https://pub.dev"
source: hosted
version: "0.10.12"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.12.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
url: "https://pub.dev"
source: hosted
version: "1.25.8"
test_api:
dependency: transitive
description:
name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.3"
test_core:
dependency: transitive
description:
name: test_core
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
url: "https://pub.dev"
source: hosted
version: "0.6.5"
timing:
dependency: transitive
description:
name: timing
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
version: "14.3.1"
watcher:
dependency: transitive
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
url: "https://pub.dev"
source: hosted
version: "0.1.6"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.5.0 <4.0.0"

View file

@ -0,0 +1,19 @@
name: platform_container
description: Laravel-style container implementation for the Protevus Platform
version: 0.1.0
publish_to: none
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
platform_contracts:
path: ../contracts
meta: ^1.9.0
collection: ^1.17.0
dev_dependencies:
test: ^1.24.0
mockito: ^5.4.0
build_runner: ^2.4.0
lints: ^2.1.0

View file

@ -0,0 +1,257 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import '../laravel_container_test.mocks.dart';
import '../stubs.dart';
@GenerateMocks([
ReflectorContract,
ReflectedClassContract,
ReflectedInstanceContract,
ReflectedFunctionContract,
ReflectedParameterContract,
ReflectedTypeContract
])
void main() {
late IlluminateContainer container;
late MockReflectorContract reflector;
late MockReflectedClassContract reflectedClass;
late MockReflectedInstanceContract reflectedInstance;
late MockReflectedFunctionContract reflectedFunction;
late MockReflectedParameterContract reflectedParameter;
late MockReflectedTypeContract reflectedType;
setUp(() {
reflector = MockReflectorContract();
reflectedClass = MockReflectedClassContract();
reflectedInstance = MockReflectedInstanceContract();
reflectedFunction = MockReflectedFunctionContract();
reflectedParameter = MockReflectedParameterContract();
reflectedType = MockReflectedTypeContract();
container = IlluminateContainer(reflector);
// Setup default reflection behavior
when(reflector.reflectClass(any)).thenReturn(reflectedClass);
when(reflectedClass.newInstance('', [])).thenReturn(reflectedInstance);
});
group('Container Basic Resolution', () {
test('testClosureResolution', () {
container.bind<String>((c) => 'Taylor');
expect(container.make<String>(), equals('Taylor'));
});
test('testBindIfDoesntRegisterIfServiceAlreadyRegistered', () {
container.bind<String>((c) => 'Taylor');
container.bindIf<String>((c) => 'Dayle');
expect(container.make<String>(), equals('Taylor'));
});
test('testBindIfDoesRegisterIfServiceNotRegisteredYet', () {
container.bindIf<String>((c) => 'Dayle');
expect(container.make<String>(), equals('Dayle'));
});
test('testAutoConcreteResolution', () {
final instance = ContainerConcreteStub();
when(reflectedInstance.reflectee).thenReturn(instance);
expect(container.make<ContainerConcreteStub>(),
isA<ContainerConcreteStub>());
});
});
group('Container Singleton', () {
test('testSharedClosureResolution', () {
container
.singleton<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
});
test('testSingletonIfDoesntRegisterIfBindingAlreadyRegistered', () {
container
.singleton<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
container
.singletonIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
});
test('testSingletonIfDoesRegisterIfBindingNotRegisteredYet', () {
container
.singletonIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
});
test('testBindingAnInstanceAsShared', () {
final instance = ContainerConcreteStub();
container.instance<ContainerConcreteStub>(instance);
expect(
identical(container.make<ContainerConcreteStub>(), instance), isTrue);
});
});
group('Container Scoped', () {
test('testScopedClosureResolution', () {
container.scoped<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
container.forgetScopedInstances();
final third = container.make<ContainerConcreteStub>();
expect(identical(second, third), isFalse);
});
test('testScopedIfDoesntRegisterIfBindingAlreadyRegistered', () {
container.scoped<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
container.scopedIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
});
test('testScopedIfDoesRegisterIfBindingNotRegisteredYet', () {
container.scopedIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
final first = container.make<ContainerConcreteStub>();
final second = container.make<ContainerConcreteStub>();
expect(identical(first, second), isTrue);
});
});
group('Container Dependencies', () {
test('testAbstractToConcreteResolution', () {
final impl = ContainerImplementationStub();
final dependent = ContainerDependentStub(impl);
when(reflectedInstance.reflectee).thenReturn(dependent);
container
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
final instance = container.make<ContainerDependentStub>();
expect(instance.impl, isA<ContainerImplementationStub>());
});
test('testNestedDependencyResolution', () {
final impl = ContainerImplementationStub();
final dependent = ContainerDependentStub(impl);
final nested = ContainerNestedDependentStub(dependent);
when(reflectedInstance.reflectee).thenReturn(nested);
container
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
final instance = container.make<ContainerNestedDependentStub>();
expect(instance.inner, isA<ContainerDependentStub>());
expect(instance.inner.impl, isA<ContainerImplementationStub>());
});
test('testContainerIsPassedToResolvers', () {
container.bind<ContainerContract>((c) => c);
final resolved = container.make<ContainerContract>();
expect(identical(resolved, container), isTrue);
});
});
group('Container Aliases', () {
test('testAliases', () {
final impl = ContainerImplementationStub('bar');
when(reflectedInstance.reflectee).thenReturn(impl);
container.bind<IContainerContractStub>((c) => impl);
container.alias(IContainerContractStub, ContainerImplementationStub);
expect(
container.make<IContainerContractStub>().getValue(), equals('bar'));
expect(container.make<ContainerImplementationStub>().getValue(),
equals('bar'));
expect(container.isAlias('ContainerImplementationStub'), isTrue);
});
test('testAliasesWithArrayOfParameters', () {
final impl = ContainerImplementationStub('foo');
when(reflectedInstance.reflectee).thenReturn(impl);
container.bind<IContainerContractStub>((c) => impl);
container.alias(IContainerContractStub, ContainerImplementationStub);
expect(
container.make<IContainerContractStub>().getValue(), equals('foo'));
expect(container.make<ContainerImplementationStub>().getValue(),
equals('foo'));
});
test('testGetAliasRecursive', () {
final impl = ContainerImplementationStub('foo');
when(reflectedInstance.reflectee).thenReturn(impl);
// Bind the implementation to the interface
container.bind<IContainerContractStub>((c) => impl);
// Create alias chain in reverse order
container.alias(ContainerImplementationStub, StubAlias);
container.alias(IContainerContractStub, ContainerImplementationStub);
// Verify immediate aliases
expect(
container.getAlias(StubAlias), equals(ContainerImplementationStub));
expect(container.getAlias(ContainerImplementationStub),
equals(IContainerContractStub));
// Verify instance resolution through alias chain
final instance = container.make<IContainerContractStub>();
expect(instance.getValue(), equals('foo'));
});
});
group('Container State', () {
test('testBindingsCanBeOverridden', () {
container.bind<String>((c) => 'bar');
container.bind<String>((c) => 'baz');
expect(container.make<String>(), equals('baz'));
});
test('testContainerFlushFlushesAllBindingsAliasesAndResolvedInstances', () {
container
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
container.bind<ContainerConcreteStub>((c) => ContainerConcreteStub());
container.tag([ContainerConcreteStub], 'services');
container.alias(IContainerContractStub, ContainerImplementationStub);
expect(container.has<IContainerContractStub>(), isTrue);
expect(container.has<ContainerConcreteStub>(), isTrue);
expect(container.isAlias('ContainerImplementationStub'), isTrue);
container.flush();
expect(container.has<IContainerContractStub>(), isFalse);
expect(container.has<ContainerConcreteStub>(), isFalse);
expect(container.isAlias('ContainerImplementationStub'), isFalse);
});
test('testForgetInstanceForgetsInstance', () {
final instance = ContainerConcreteStub();
container.instance<ContainerConcreteStub>(instance);
expect(container.has<ContainerConcreteStub>(), isTrue);
container.forgetInstance(ContainerConcreteStub);
expect(container.has<ContainerConcreteStub>(), isFalse);
});
test('testForgetInstancesForgetsAllInstances', () {
final instance1 = ContainerConcreteStub();
final instance2 = ContainerImplementationStub();
container.instance<ContainerConcreteStub>(instance1);
container.instance<ContainerImplementationStub>(instance2);
expect(container.has<ContainerConcreteStub>(), isTrue);
expect(container.has<ContainerImplementationStub>(), isTrue);
container.forgetInstances();
expect(container.has<ContainerConcreteStub>(), isFalse);
expect(container.has<ContainerImplementationStub>(), isFalse);
});
});
}

View file

@ -0,0 +1,126 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'container_test.mocks.dart';
@GenerateMocks(
[ReflectorContract, ReflectedTypeContract, ReflectedInstanceContract])
void main() {
late IlluminateContainer container;
late MockReflectorContract reflector;
late MockReflectedTypeContract reflectedType;
late MockReflectedInstanceContract reflectedInstance;
setUp(() {
reflector = MockReflectorContract();
reflectedType = MockReflectedTypeContract();
reflectedInstance = MockReflectedInstanceContract();
container = IlluminateContainer(reflector);
// Setup default reflection behavior
when(reflector.reflectClass(any)).thenReturn(null);
});
group('Container', () {
test('isRoot returns true for root container', () {
expect(container.isRoot, isTrue);
});
test('isRoot returns false for child container', () {
final child = container.createChild();
expect(child.isRoot, isFalse);
});
test('has returns true for registered singleton', () {
container.registerSingleton<String>('test');
expect(container.has<String>(), isTrue);
});
test('has returns true for registered factory', () {
container.registerFactory<String>((c) => 'test');
expect(container.has<String>(), isTrue);
});
test('has returns true for registered lazy singleton', () {
container.registerLazySingleton<String>((c) => 'test');
expect(container.has<String>(), isTrue);
});
test('hasNamed returns true for registered named singleton', () {
container.registerNamedSingleton<String>('test.name', 'test');
expect(container.hasNamed('test.name'), isTrue);
});
test('make returns singleton instance', () {
container.registerSingleton<String>('test');
expect(container.make<String>(), equals('test'));
});
test('make creates new instance for factory', () {
var count = 0;
container.registerFactory<String>((c) => 'test${count++}');
expect(container.make<String>(), equals('test0'));
expect(container.make<String>(), equals('test1'));
});
test('make returns same instance for lazy singleton', () {
var count = 0;
container.registerLazySingleton<String>((c) => 'test${count++}');
expect(container.make<String>(), equals('test0'));
expect(container.make<String>(), equals('test0'));
});
test('makeAsync returns Future for async dependency', () async {
// Setup mock behavior
when(reflector.reflectFutureOf(String)).thenReturn(reflectedType);
when(reflectedType.newInstance('', [])).thenReturn(reflectedInstance);
when(reflectedInstance.reflectee).thenAnswer((_) => Future.value('test'));
final result = await container.makeAsync<String>();
expect(result, equals('test'));
});
test('findByName returns named singleton', () {
container.registerNamedSingleton<String>('test.name', 'test');
expect(container.findByName<String>('test.name'), equals('test'));
});
test('child container inherits parent bindings', () {
container.registerSingleton<String>('test');
final child = container.createChild();
expect(child.make<String>(), equals('test'));
});
test('child container can override parent bindings', () {
container.registerSingleton<String>('parent');
final child = container.createChild() as IlluminateContainer;
child.registerSingleton<String>('child');
expect(child.make<String>(), equals('child'));
expect(container.make<String>(), equals('parent'));
});
test('throws when making unregistered type without reflection', () {
expect(() => container.make<String>(), throwsStateError);
});
test('throws when making named singleton that does not exist', () {
expect(() => container.findByName<String>('missing'), throwsStateError);
});
test('throws when registering duplicate singleton', () {
container.registerSingleton<String>('test');
expect(
() => container.registerSingleton<String>('test2'), throwsStateError);
});
test('throws when registering duplicate named singleton', () {
container.registerNamedSingleton<String>('test.name', 'test');
expect(
() => container.registerNamedSingleton<String>('test.name', 'test2'),
throwsStateError);
});
});
}

View file

@ -0,0 +1,241 @@
// Mocks generated by Mockito 5.4.4 from annotations
// in platform_illuminate_container/test/container_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i3;
import 'package:platform_contracts/src/reflection/reflector_contract.dart'
as _i2;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeReflectedTypeContract_0 extends _i1.SmartFake
implements _i2.ReflectedTypeContract {
_FakeReflectedTypeContract_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeType_1 extends _i1.SmartFake implements Type {
_FakeType_1(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeReflectedInstanceContract_2 extends _i1.SmartFake
implements _i2.ReflectedInstanceContract {
_FakeReflectedInstanceContract_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeReflectedClassContract_3 extends _i1.SmartFake
implements _i2.ReflectedClassContract {
_FakeReflectedClassContract_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [ReflectorContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectorContract extends _i1.Mock implements _i2.ReflectorContract {
MockReflectorContract() {
_i1.throwOnMissingStub(this);
}
@override
String? getName(Symbol? symbol) => (super.noSuchMethod(Invocation.method(
#getName,
[symbol],
)) as String?);
@override
_i2.ReflectedClassContract? reflectClass(Type? clazz) =>
(super.noSuchMethod(Invocation.method(
#reflectClass,
[clazz],
)) as _i2.ReflectedClassContract?);
@override
_i2.ReflectedFunctionContract? reflectFunction(Function? function) =>
(super.noSuchMethod(Invocation.method(
#reflectFunction,
[function],
)) as _i2.ReflectedFunctionContract?);
@override
_i2.ReflectedTypeContract? reflectType(Type? type) =>
(super.noSuchMethod(Invocation.method(
#reflectType,
[type],
)) as _i2.ReflectedTypeContract?);
@override
_i2.ReflectedInstanceContract? reflectInstance(Object? object) =>
(super.noSuchMethod(Invocation.method(
#reflectInstance,
[object],
)) as _i2.ReflectedInstanceContract?);
@override
_i2.ReflectedTypeContract reflectFutureOf(Type? type) => (super.noSuchMethod(
Invocation.method(
#reflectFutureOf,
[type],
),
returnValue: _FakeReflectedTypeContract_0(
this,
Invocation.method(
#reflectFutureOf,
[type],
),
),
) as _i2.ReflectedTypeContract);
}
/// A class which mocks [ReflectedTypeContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedTypeContract extends _i1.Mock
implements _i2.ReflectedTypeContract {
MockReflectedTypeContract() {
_i1.throwOnMissingStub(this);
}
@override
String get name => (super.noSuchMethod(
Invocation.getter(#name),
returnValue: _i3.dummyValue<String>(
this,
Invocation.getter(#name),
),
) as String);
@override
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
(super.noSuchMethod(
Invocation.getter(#typeParameters),
returnValue: <_i2.ReflectedTypeParameterContract>[],
) as List<_i2.ReflectedTypeParameterContract>);
@override
Type get reflectedType => (super.noSuchMethod(
Invocation.getter(#reflectedType),
returnValue: _FakeType_1(
this,
Invocation.getter(#reflectedType),
),
) as Type);
@override
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
Invocation.method(
#isAssignableTo,
[other],
),
returnValue: false,
) as bool);
@override
_i2.ReflectedInstanceContract newInstance(
String? constructorName,
List<dynamic>? positionalArguments, [
Map<String, dynamic>? namedArguments = const {},
List<Type>? typeArguments = const [],
]) =>
(super.noSuchMethod(
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
),
) as _i2.ReflectedInstanceContract);
}
/// A class which mocks [ReflectedInstanceContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedInstanceContract extends _i1.Mock
implements _i2.ReflectedInstanceContract {
MockReflectedInstanceContract() {
_i1.throwOnMissingStub(this);
}
@override
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
Invocation.getter(#type),
returnValue: _FakeReflectedTypeContract_0(
this,
Invocation.getter(#type),
),
) as _i2.ReflectedTypeContract);
@override
_i2.ReflectedClassContract get clazz => (super.noSuchMethod(
Invocation.getter(#clazz),
returnValue: _FakeReflectedClassContract_3(
this,
Invocation.getter(#clazz),
),
) as _i2.ReflectedClassContract);
@override
_i2.ReflectedInstanceContract getField(String? name) => (super.noSuchMethod(
Invocation.method(
#getField,
[name],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#getField,
[name],
),
),
) as _i2.ReflectedInstanceContract);
}

View file

@ -0,0 +1,293 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_container/platform_container.dart';
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'laravel_container_test.mocks.dart';
// Test classes
abstract class PaymentGateway {}
class StripeGateway implements PaymentGateway {}
class PayPalGateway implements PaymentGateway {}
class Service {}
class SpecialService extends Service {}
class Client {
final Service service;
Client(this.service);
}
@GenerateMocks([
ReflectorContract,
ReflectedClassContract,
ReflectedInstanceContract,
ReflectedFunctionContract,
ReflectedParameterContract,
ReflectedTypeContract
])
void main() {
late IlluminateContainer container;
late MockReflectorContract reflector;
late MockReflectedClassContract reflectedClass;
late MockReflectedInstanceContract reflectedInstance;
late MockReflectedFunctionContract reflectedFunction;
late MockReflectedParameterContract reflectedParameter;
late MockReflectedTypeContract reflectedType;
setUp(() {
reflector = MockReflectorContract();
reflectedClass = MockReflectedClassContract();
reflectedInstance = MockReflectedInstanceContract();
reflectedFunction = MockReflectedFunctionContract();
reflectedParameter = MockReflectedParameterContract();
reflectedType = MockReflectedTypeContract();
container = IlluminateContainer(reflector);
// Setup default reflection behavior
when(reflector.reflectClass(any)).thenReturn(null);
when(reflector.reflectFunction(any)).thenReturn(null);
});
group('Laravel Container', () {
test('contextual binding with when/needs/give', () {
// When we set up a contextual binding
container.when(Client).needs<Service>().give(SpecialService());
// Then the contextual binding should be used
when(reflector.reflectClass(Client)).thenReturn(reflectedClass);
when(reflectedClass.newInstance('', [])).thenReturn(reflectedInstance);
when(reflectedInstance.reflectee).thenReturn(Client(SpecialService()));
final client = container.make<Client>();
expect(client.service, isA<SpecialService>());
});
test('method injection with call', () {
void method(Service service) {}
// Setup reflection mocks
when(reflector.reflectFunction(method)).thenReturn(reflectedFunction);
when(reflectedFunction.parameters).thenReturn([reflectedParameter]);
when(reflectedParameter.type).thenReturn(reflectedType);
when(reflectedType.reflectedType).thenReturn(Service);
// Register service
final service = Service();
container.registerSingleton(service);
// When we call the method through the container
container.call(method);
// Then dependencies should be injected
verify(reflector.reflectFunction(method)).called(1);
});
test('resolution hooks', () {
// Given some resolution hooks
final resolving = <String>[];
final testValue = 'test';
// Register hooks with explicit type parameters
void beforeCallback(ContainerContract c, String? i) =>
resolving.add('before');
void resolvingCallback(ContainerContract c, String i) =>
resolving.add('resolving');
void afterCallback(ContainerContract c, String i) =>
resolving.add('after');
container.beforeResolving<String>(beforeCallback);
container.resolving<String>(resolvingCallback);
container.afterResolving<String>(afterCallback);
// Register a value to resolve
container.registerSingleton<String>(testValue);
// When we resolve a type
container.make<String>();
// Then hooks should be called in order
expect(resolving, equals(['before', 'resolving', 'after']));
});
test('method binding', () {
// Setup reflection mocks
when(reflector.reflectFunction(any)).thenReturn(reflectedFunction);
when(reflectedFunction.parameters).thenReturn([]);
// Register a method
String boundMethod() => 'bound';
container.bindMethod('test', boundMethod);
// Call a test method
String testMethod() => 'test';
final result = container.call(testMethod);
// Verify the method was called
verify(reflector.reflectFunction(any)).called(1);
expect(result, equals('test'));
});
test('tagged bindings', () {
// Create gateway instances
final stripeGateway = StripeGateway();
final paypalGateway = PayPalGateway();
// Register factories for concrete types
container.registerFactory<StripeGateway>((c) => stripeGateway);
container.registerFactory<PayPalGateway>((c) => paypalGateway);
// Register types in order
container.tag([StripeGateway, PayPalGateway], 'gateways');
// When we resolve tagged bindings
final gateways = container.tagged<PaymentGateway>('gateways');
// Then all tagged instances should be returned in order
expect(gateways.length, equals(2));
expect(gateways[0], same(stripeGateway));
expect(gateways[1], same(paypalGateway));
});
test('shared bindings', () {
// Given a shared binding
container.bind<String>((c) => 'test', shared: true);
// When we resolve multiple times
final first = container.make<String>();
final second = container.make<String>();
// Then the same instance should be returned
expect(identical(first, second), isTrue);
});
test('child container inherits bindings', () {
// Given a parent binding
container.bind<String>((c) => 'parent');
// When we create a child container
final child = container.createChild();
// Then the child should inherit bindings
expect(child.make<String>(), equals('parent'));
});
test('child container can override bindings', () {
// Given a parent binding
container.registerFactory<String>((c) => 'parent');
// When we override in child
final child = container.createChild();
child.registerFactory<String>((c) => 'child');
// Then child should use its own binding
expect(child.make<String>(), equals('child'));
expect(container.make<String>(), equals('parent'));
});
test('scoped bindings', () {
// Given a scoped binding
var counter = 0;
container.scoped<String>((c) => 'scoped${counter++}');
// When we resolve multiple times
final first = container.make<String>();
final second = container.make<String>();
// Then the same instance should be returned
expect(first, equals(second));
// When we forget scoped instances
container.forgetScopedInstances();
// Then a new instance should be created
final third = container.make<String>();
expect(third, isNot(equals(second)));
});
test('type aliases', () {
// Given a binding and an alias
container.bind<PaymentGateway>((c) => StripeGateway());
container.alias(PaymentGateway, StripeGateway);
// When we check if it's an alias
final isAlias = container.isAlias('StripeGateway');
// Then it should be true
expect(isAlias, isTrue);
// And the alias should resolve to the original type
expect(container.getAlias(StripeGateway), equals(PaymentGateway));
});
test('extending instances', () {
print('Starting extending instances test');
// Given a binding and an extender
var extended = false;
print('Setting up binding and extender');
container.bind<Service>((c) => Service());
container.extend(Service, (instance) {
print('Extender called');
extended = true;
});
print('Making instance');
// When we make an instance
container.make<Service>();
print('Extended value: $extended');
// Then the extender should be called
expect(extended, isTrue);
// And we can get the extenders
expect(container.getExtenders(Service).length, equals(1));
// And we can forget them
container.forgetExtenders(Service);
expect(container.getExtenders(Service).length, equals(0));
});
test('rebinding callbacks', () {
// Given a binding and a rebind callback
var rebound = false;
container.bind<Service>((c) => Service());
container.rebinding(Service, (c, i) => rebound = true);
// When we refresh an instance
final target = {'method': (Service s) {}};
container.refresh(Service, target, 'method');
// Then the callback should be called
expect(rebound, isTrue);
});
test('container flushing', () {
// Given some bindings and instances
container.bind<Service>((c) => Service());
container.registerSingleton(PayPalGateway());
container.registerNamedSingleton('test', 'value');
container.tag([Service], 'services');
container.when(Client).needs<Service>().give(SpecialService());
container.bindMethod('test', () {});
container.alias(PaymentGateway, PayPalGateway);
container.extend(Service, (i) {});
container.rebinding(Service, (c, i) {});
container.scoped<String>((c) => 'scoped');
container.beforeResolving<Service>((c, i) {});
// When we flush the container
container.flush();
// Then everything should be cleared
expect(container.has<Service>(), isFalse);
expect(container.hasNamed('test'), isFalse);
expect(() => container.tagged('services'), throwsStateError);
expect(container.getExtenders(Service).length, equals(0));
});
});
}

View file

@ -0,0 +1,447 @@
// Mocks generated by Mockito 5.4.4 from annotations
// in platform_illuminate_container/test/laravel_container_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i3;
import 'package:platform_contracts/src/reflection/reflector_contract.dart'
as _i2;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeReflectedTypeContract_0 extends _i1.SmartFake
implements _i2.ReflectedTypeContract {
_FakeReflectedTypeContract_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeType_1 extends _i1.SmartFake implements Type {
_FakeType_1(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeReflectedInstanceContract_2 extends _i1.SmartFake
implements _i2.ReflectedInstanceContract {
_FakeReflectedInstanceContract_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeReflectedClassContract_3 extends _i1.SmartFake
implements _i2.ReflectedClassContract {
_FakeReflectedClassContract_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [ReflectorContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectorContract extends _i1.Mock implements _i2.ReflectorContract {
MockReflectorContract() {
_i1.throwOnMissingStub(this);
}
@override
String? getName(Symbol? symbol) => (super.noSuchMethod(Invocation.method(
#getName,
[symbol],
)) as String?);
@override
_i2.ReflectedClassContract? reflectClass(Type? clazz) =>
(super.noSuchMethod(Invocation.method(
#reflectClass,
[clazz],
)) as _i2.ReflectedClassContract?);
@override
_i2.ReflectedFunctionContract? reflectFunction(Function? function) =>
(super.noSuchMethod(Invocation.method(
#reflectFunction,
[function],
)) as _i2.ReflectedFunctionContract?);
@override
_i2.ReflectedTypeContract? reflectType(Type? type) =>
(super.noSuchMethod(Invocation.method(
#reflectType,
[type],
)) as _i2.ReflectedTypeContract?);
@override
_i2.ReflectedInstanceContract? reflectInstance(Object? object) =>
(super.noSuchMethod(Invocation.method(
#reflectInstance,
[object],
)) as _i2.ReflectedInstanceContract?);
@override
_i2.ReflectedTypeContract reflectFutureOf(Type? type) => (super.noSuchMethod(
Invocation.method(
#reflectFutureOf,
[type],
),
returnValue: _FakeReflectedTypeContract_0(
this,
Invocation.method(
#reflectFutureOf,
[type],
),
),
) as _i2.ReflectedTypeContract);
}
/// A class which mocks [ReflectedClassContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedClassContract extends _i1.Mock
implements _i2.ReflectedClassContract {
MockReflectedClassContract() {
_i1.throwOnMissingStub(this);
}
@override
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
Invocation.getter(#annotations),
returnValue: <_i2.ReflectedInstanceContract>[],
) as List<_i2.ReflectedInstanceContract>);
@override
List<_i2.ReflectedFunctionContract> get constructors => (super.noSuchMethod(
Invocation.getter(#constructors),
returnValue: <_i2.ReflectedFunctionContract>[],
) as List<_i2.ReflectedFunctionContract>);
@override
List<_i2.ReflectedDeclarationContract> get declarations =>
(super.noSuchMethod(
Invocation.getter(#declarations),
returnValue: <_i2.ReflectedDeclarationContract>[],
) as List<_i2.ReflectedDeclarationContract>);
@override
String get name => (super.noSuchMethod(
Invocation.getter(#name),
returnValue: _i3.dummyValue<String>(
this,
Invocation.getter(#name),
),
) as String);
@override
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
(super.noSuchMethod(
Invocation.getter(#typeParameters),
returnValue: <_i2.ReflectedTypeParameterContract>[],
) as List<_i2.ReflectedTypeParameterContract>);
@override
Type get reflectedType => (super.noSuchMethod(
Invocation.getter(#reflectedType),
returnValue: _FakeType_1(
this,
Invocation.getter(#reflectedType),
),
) as Type);
@override
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
Invocation.method(
#isAssignableTo,
[other],
),
returnValue: false,
) as bool);
@override
_i2.ReflectedInstanceContract newInstance(
String? constructorName,
List<dynamic>? positionalArguments, [
Map<String, dynamic>? namedArguments = const {},
List<Type>? typeArguments = const [],
]) =>
(super.noSuchMethod(
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
),
) as _i2.ReflectedInstanceContract);
}
/// A class which mocks [ReflectedInstanceContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedInstanceContract extends _i1.Mock
implements _i2.ReflectedInstanceContract {
MockReflectedInstanceContract() {
_i1.throwOnMissingStub(this);
}
@override
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
Invocation.getter(#type),
returnValue: _FakeReflectedTypeContract_0(
this,
Invocation.getter(#type),
),
) as _i2.ReflectedTypeContract);
@override
_i2.ReflectedClassContract get clazz => (super.noSuchMethod(
Invocation.getter(#clazz),
returnValue: _FakeReflectedClassContract_3(
this,
Invocation.getter(#clazz),
),
) as _i2.ReflectedClassContract);
@override
_i2.ReflectedInstanceContract getField(String? name) => (super.noSuchMethod(
Invocation.method(
#getField,
[name],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#getField,
[name],
),
),
) as _i2.ReflectedInstanceContract);
}
/// A class which mocks [ReflectedFunctionContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedFunctionContract extends _i1.Mock
implements _i2.ReflectedFunctionContract {
MockReflectedFunctionContract() {
_i1.throwOnMissingStub(this);
}
@override
String get name => (super.noSuchMethod(
Invocation.getter(#name),
returnValue: _i3.dummyValue<String>(
this,
Invocation.getter(#name),
),
) as String);
@override
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
(super.noSuchMethod(
Invocation.getter(#typeParameters),
returnValue: <_i2.ReflectedTypeParameterContract>[],
) as List<_i2.ReflectedTypeParameterContract>);
@override
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
Invocation.getter(#annotations),
returnValue: <_i2.ReflectedInstanceContract>[],
) as List<_i2.ReflectedInstanceContract>);
@override
List<_i2.ReflectedParameterContract> get parameters => (super.noSuchMethod(
Invocation.getter(#parameters),
returnValue: <_i2.ReflectedParameterContract>[],
) as List<_i2.ReflectedParameterContract>);
@override
bool get isGetter => (super.noSuchMethod(
Invocation.getter(#isGetter),
returnValue: false,
) as bool);
@override
bool get isSetter => (super.noSuchMethod(
Invocation.getter(#isSetter),
returnValue: false,
) as bool);
@override
_i2.ReflectedInstanceContract invoke(Invocation? invocation) =>
(super.noSuchMethod(
Invocation.method(
#invoke,
[invocation],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#invoke,
[invocation],
),
),
) as _i2.ReflectedInstanceContract);
}
/// A class which mocks [ReflectedParameterContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedParameterContract extends _i1.Mock
implements _i2.ReflectedParameterContract {
MockReflectedParameterContract() {
_i1.throwOnMissingStub(this);
}
@override
String get name => (super.noSuchMethod(
Invocation.getter(#name),
returnValue: _i3.dummyValue<String>(
this,
Invocation.getter(#name),
),
) as String);
@override
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
Invocation.getter(#annotations),
returnValue: <_i2.ReflectedInstanceContract>[],
) as List<_i2.ReflectedInstanceContract>);
@override
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
Invocation.getter(#type),
returnValue: _FakeReflectedTypeContract_0(
this,
Invocation.getter(#type),
),
) as _i2.ReflectedTypeContract);
@override
bool get isRequired => (super.noSuchMethod(
Invocation.getter(#isRequired),
returnValue: false,
) as bool);
@override
bool get isNamed => (super.noSuchMethod(
Invocation.getter(#isNamed),
returnValue: false,
) as bool);
}
/// A class which mocks [ReflectedTypeContract].
///
/// See the documentation for Mockito's code generation for more information.
class MockReflectedTypeContract extends _i1.Mock
implements _i2.ReflectedTypeContract {
MockReflectedTypeContract() {
_i1.throwOnMissingStub(this);
}
@override
String get name => (super.noSuchMethod(
Invocation.getter(#name),
returnValue: _i3.dummyValue<String>(
this,
Invocation.getter(#name),
),
) as String);
@override
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
(super.noSuchMethod(
Invocation.getter(#typeParameters),
returnValue: <_i2.ReflectedTypeParameterContract>[],
) as List<_i2.ReflectedTypeParameterContract>);
@override
Type get reflectedType => (super.noSuchMethod(
Invocation.getter(#reflectedType),
returnValue: _FakeType_1(
this,
Invocation.getter(#reflectedType),
),
) as Type);
@override
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
Invocation.method(
#isAssignableTo,
[other],
),
returnValue: false,
) as bool);
@override
_i2.ReflectedInstanceContract newInstance(
String? constructorName,
List<dynamic>? positionalArguments, [
Map<String, dynamic>? namedArguments = const {},
List<Type>? typeArguments = const [],
]) =>
(super.noSuchMethod(
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
returnValue: _FakeReflectedInstanceContract_2(
this,
Invocation.method(
#newInstance,
[
constructorName,
positionalArguments,
namedArguments,
typeArguments,
],
),
),
) as _i2.ReflectedInstanceContract);
}

View file

@ -0,0 +1,86 @@
// Test classes ported from Laravel's ContainerTest.php
// Basic concrete class
class ContainerConcreteStub {}
// Interface and implementations
abstract class IContainerContractStub {
String getValue();
}
class ContainerImplementationStub implements IContainerContractStub {
final String value;
ContainerImplementationStub([this.value = 'implementation']);
@override
String getValue() => value;
}
class ContainerImplementationStubTwo implements IContainerContractStub {
@override
String getValue() => 'implementation2';
}
// Classes with dependencies
class ContainerDependentStub {
final IContainerContractStub impl;
ContainerDependentStub(this.impl);
}
class ContainerNestedDependentStub {
final ContainerDependentStub inner;
ContainerNestedDependentStub(this.inner);
}
// Classes with default values
class ContainerDefaultValueStub {
final ContainerConcreteStub stub;
final String default_;
ContainerDefaultValueStub(this.stub, [this.default_ = 'taylor']);
}
// Classes with mixed parameters
class ContainerMixedPrimitiveStub {
final int first;
final ContainerConcreteStub stub;
final int last;
ContainerMixedPrimitiveStub(this.first, this.stub, this.last);
}
// Classes for variable injection
class ContainerInjectVariableStub {
final String something;
ContainerInjectVariableStub(ContainerConcreteStub concrete, this.something);
}
class ContainerInjectVariableStubWithInterface
implements IContainerContractStub {
final String something;
ContainerInjectVariableStubWithInterface(
ContainerConcreteStub concrete, this.something);
@override
String getValue() => something;
}
// Class for contextual binding
class ContainerContextualBindingCallTarget {
IContainerContractStub work(IContainerContractStub stub) => stub;
}
// Classes for circular dependency testing
class CircularAStub {
CircularAStub(CircularBStub b);
}
class CircularBStub {
CircularBStub(CircularCStub c);
}
class CircularCStub {
CircularCStub(CircularAStub a);
}
// Additional test types
class StubAlias implements IContainerContractStub {
@override
String getValue() => 'alias';
}