Как указать класс для использования при имитации свойства?
Я обнаружил, что часто подделываю IDbSet из Entity Framework. У меня обычно есть такой интерфейс:
public interface IContext : IDisposable
{
IDbSet<Cat> Cats { get; set; }
IDbSet<Dogs> Dogs { get; set; }
}
Который я подделываю так:
IContext context = A.Fake<IContext>();
context.Cats = new FakeDbSet<Cat>();
context.Dogs = new FakeDbSet<Dogs>();
Эти последние две строки кода становятся болью.
FakeDbSet - это пользовательский класс, который мы всегда хотим использовать вместо фейка FakeItEasy.
Есть ли какой-то способ, которым я могу просто сказать FakeItEasy, что везде, где он видит IDbSet, использовать FakeDbSet?
1 ответ
Есть ли какой-то способ, которым я могу просто сказать FakeItEasy, что везде, где он видит IDbSet, использовать FakeDbSet?
Не таким образом, нет. Существуют пользовательские Dummies, возможности которых значительно улучшатся в следующем выпуске 2.0, но в настоящее время свойства не возвращают Dummies, когда они могут возвращать поддельный тип (см. Проблему 156 для получения слишком большой информации об этом). В противном случае у вас все будет готово.
В противном случае лучший вариант на самом деле - использовать отражение, чтобы посмотреть типы возвращаемых свойств и соответственно установить значение.
Вы могли бы использовать недавно расширенные возможности IFakeConfigurator в бета-версиях 2.0 в качестве хука, чтобы включить это поведение, чтобы у каждого созданного подделки были свои свойства изучены и желаемый FakeDbSet
добавлено.
Что-то вроде этого:
public class PropertiesUseFakeDbSetFakeConfigurator : FakeConfigurator<IContext>
{
protected override void ConfigureFake(IContext fakeObject)
{
var fakeObjectType = fakeObject.GetType();
var properties = fakeObjectType.GetProperties(
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.GetProperty |
BindingFlags.SetProperty);
foreach (var propertyInfo in properties)
{
var propertyType = propertyInfo.PropertyType;
if (propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof (IDbSet<>))
{
var typeInTheSet = propertyType.GetGenericArguments()[0];
var fakeDbSetType = typeof (FakeDbSet<>).MakeGenericType(typeInTheSet);
var fakePropertyValue = Activator.CreateInstance(fakeDbSetType);
propertyInfo.SetValue(fakeObject, fakePropertyValue, null);
}
}
}
}
сделал бы этот проход:
[Test]
public void Properties_should_be_FakeDbSets()
{
IContext context = A.Fake<IContext>();
Assert.That(context.Cats, Is.InstanceOf<FakeDbSet<Cat>>());
Assert.That(context.Dogs, Is.InstanceOf<FakeDbSet<Dog>>());
}
Если у вас есть несколько классов, таких как IContext
в вашем решении, вы можете реализовать IFakeConfigurator
напрямую, а не используя FakeConfigurator<T>
, Это требует немного больше работы, но предоставляет более сложный способ определить, какие подделки настроены. FakeConfigurator<IContext>
буду настраивать только подделку IContext
s.