2015-03-26 1 views
2

Я нахожу, что я часто подделываю 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?

+0

Я знаю, что могу отразиться на подделке и назначить FakeDbSet самостоятельно, но я надеюсь, что есть встроенный способ. –

ответ

3

Есть ли способ, которым я могу просто сказать FakeItEasy, что везде, где он видит IDbSet, используйте FakeDbSet?

Не таким образом, нет. Есть custom Dummies, чьи полномочия значительно улучшены в предстоящей версии 2.0, но в настоящее время свойства не возвращают «чайники», когда они могут вернуть поддельный тип (см. issue 156, вероятно, слишком много информации об этом). В противном случае все будет готово.

В противном случае лучшим вариантом является использование отражения, чтобы посмотреть типы возвращаемых свойств и установить значение соответствующим образом.

Вы можете использовать newly-expanded IFakeConfigurator powers in the 2.0 betas как крючок, чтобы включить эту функцию, поэтому каждая созданная подделка проведет проверку ее свойств и добавит желаемый 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> будет настраивать только faked IContext s.

+0

Ничего себе, спасибо за то, что написали это время, а также всю вашу работу над FakeItEasy. Так держать! –

+0

Нет проблем. По правде говоря, в то время как мне было бы счастливее сказать: «Переверните этот переключатель» или что-то еще, я действительно наслаждаюсь этими ... «головоломками», я думаю, я позвоню им. Конечно, это будет работать только в том случае, если для свойства есть геттер и сеттер. Для свойств Setterless потребуется больше работы для создания надлежащего 'A.CallTo'. Не огромная сделка, просто немного раздражающая. –

Смежные вопросы