using Moq; namespace Common.Types; internal class InstanceFaker { private readonly Dictionary _mocks = new(); private bool _mocksGenerated = false; public InstanceFaker() { if (typeof(T).GetConstructors().Length > 1) throw new Exception($"Multiple constructors for type {typeof(T).FullName} found. Auto resolve not possible."); GenerateMocks(); } private void GenerateMocks() { if (_mocksGenerated) return; _mocksGenerated = true; var constructor = typeof(T).GetConstructors()[0]; var parameters = constructor.GetParameters(); foreach (var parameter in parameters) { if (!parameter.ParameterType.IsInterface) throw new Exception($"Constructor parameter {parameter.Name} of type {parameter.ParameterType.FullName} is not an interface, cannot mock."); _mocks.Add(parameter.ParameterType, CreateMock(parameter.ParameterType)); } } private T ProcessType() { GenerateMocks(); var constructor = typeof(T).GetConstructors()[0]; var mocks = _mocks.Select(e => e.Value.Object); return (T)constructor.Invoke(mocks.Cast().ToArray()); } private Mock? CreateMock(Type type) { var creator = typeof(Mock<>).MakeGenericType(type); return Activator.CreateInstance(creator) as Mock; } public Mock? GetMock() where T : class => _mocks.GetValueOrDefault(typeof(T)) as Mock; private T _instance; public T Instance => _instance ??= ProcessType(); }