You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
using Moq;
|
|
|
|
|
|
|
|
|
|
namespace Common.Types;
|
|
|
|
|
|
|
|
|
|
internal class InstanceFaker<T>
|
|
|
|
|
{
|
|
|
|
|
private readonly Dictionary<Type, Mock> _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<object>().ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Mock? CreateMock(Type type)
|
|
|
|
|
{
|
|
|
|
|
var creator = typeof(Mock<>).MakeGenericType(type);
|
|
|
|
|
return Activator.CreateInstance(creator) as Mock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Mock<T>? GetMock<T>()
|
|
|
|
|
where T : class => _mocks.GetValueOrDefault(typeof(T)) as Mock<T>;
|
|
|
|
|
|
|
|
|
|
private T _instance;
|
|
|
|
|
|
|
|
|
|
public T Instance => _instance ??= ProcessType();
|
|
|
|
|
}
|