Поставщик значения по умолчанию потенциально является опцией. Это не то же самое, что SetReturnsDefault
, у вас намного больше контроля.
A очень быстрый MVP поставщик значений по умолчанию, например:
public class SelectiveDefaultValueProvider : DefaultValueProvider
{
private readonly string _methodName;
private readonly object _returns;
public SelectiveDefaultValueProvider(string methodName, object returns)
{
_methodName = methodName;
_returns = returns;
}
protected override object GetDefaultValue(Type type, Mock mock)
{
var lastInvocation = mock.Invocations.Last();
var methodInfo = lastInvocation.Method;
var args = lastInvocation.Arguments;
if (methodInfo.Name.Equals(_methodName))
{
return _returns;
}
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
... позволяет вам вводить некоторые решения до того, как значение будет возвращено. В этом случае я проверяю имя последнего метода вызова, если это совпадение, я возвращаю номинированный объект для возврата. Я не использую переменную args, но включил ее, чтобы показать, что вы получили не только MethodInfo
последнего вызова, но и предоставленные аргументы. Достаточно принять умные решения.
Возьмите следующий интерфейс с несколькими перегруженными методами и с тем же типом возврата:
public class ObjectToReturn
{
public Guid Id { get; set; }
}
public interface IFoo
{
ObjectToReturn MyMethod(int parameter1);
ObjectToReturn MyMethod(string parameter2);
ObjectToReturn MyMethod(int parameter1, int parameter2);
ObjectToReturn AnotherMethod();
int AValueTypeMethod();
}
Настройка теста будет выглядеть как
[Test]
public void DefaultValueProvider_ForOverloadedMethod_AllOverloadsReturnSameExpectedResult()
{
var objectToReturn = new ObjectToReturn { Id = Guid.NewGuid() };
var mock = new Mock<IFoo> { DefaultValueProvider = new SelectiveDefaultValueProvider(nameof(IFoo.MyMethod), objectToReturn) };
var mocked = mock.Object;
var result1 = mocked.MyMethod(1);
var result2 = mocked.MyMethod(1, 2);
var result3 = mocked.MyMethod("asdf");
var result4 = mocked.AnotherMethod();
var result5 = mocked.AValueTypeMethod();
Assert.Multiple(() =>
{
Assert.That(result1, Is.SameAs(objectToReturn));
Assert.That(result2, Is.SameAs(objectToReturn));
Assert.That(result3, Is.SameAs(objectToReturn));
Assert.That(result4, Is.Null);
Assert.That(result5, Is.TypeOf<int>());
});
}
Как уже упоминалось выше, это MVP, вы можете легко расширить реализацию поставщика значений по умолчанию, чтобы получить список методов / возвращаемых значений, сжать интерфейс от имен строковых методов до MethodInfo
результатов (typeof(IFoo).GetMethods().Where(x => x.Name.StartsWith("MyMethod") && x.ReturnType == typeof(ObjectToReturn))
) и т. Д.
Приятной особенностью этой методологии является то, что вам не нужно беспокоиться о построении Setup
выражений и головной боли, которую это приносит, и если вы укажете настройку для члена, она будет использовать эту настройку; поставщик значений по умолчанию используется только для элементов, для которых не задана настройка.
Рабочий раствор