Внедрение свойств с помощью AutoFixture

Я боролся со следующей проблемой в течение дня или около того. Несмотря на то, что я использовал AutoFixture в течение многих лет, я не могу решить эту проблему.

У меня есть абстрактный класс:

public abstract class AbstractClass 
{
   public IChildClass Child {get; set;}
};

ICChildInterface:

public interface IChildClass
{
   string Name {get; set;}
}

Реализация интерфейса:

public class ChildClass : IChildClass
{
   public string Name {get; set;}
}

Затем у меня есть производный класс AbstractClass:

public class MyClass : AbstractClass
{
   public MyClass()
   {
      Initialize();
   }

   private void Initialize()
   {
      var nameOfChild = Child.Name;
   }
}

В моем модульном тесте для MyClass я делаю следующее:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

var sut = fixture.Create<MyClass>();

Но получите исключение NullReferenceException для Child.Name. Я пробовал использовать Register и Customize для IChildClass и AbstractClass, но не повезло. Даже специальная реализация ISpecimenBuilder в этом случае не поможет.

У кого-нибудь есть хорошая идея, как обойти это?


person Mads Tjørnelund Toustrup    schedule 13.09.2013    source источник
comment
Если вы на мгновение забудете об AutoFixture, как вы ожидаете, что это сработает?   -  person Mark Seemann    schedule 13.09.2013
comment
Я бы пометил свойство IChildClass класса AbstractClass атрибутом Unity [Dependency] и внедрил его.   -  person Mads Tjørnelund Toustrup    schedule 13.09.2013
comment
Пробовали ли вы просто пойти var sut = new MyClass(); и посмотреть, что произойдет?   -  person Mark Seemann    schedule 13.09.2013
comment
Конечно, это решило бы эту проблему, но довольно громоздко строить тестовые данные в графе объектов. На самом деле я решил это, изменив Initialize на свойство и переименовав его. Тогда я мог бы использовать Build‹›(): var sut = fixture.Build<MyClass>().Without(x => x.Initialize).Create();   -  person Mads Tjørnelund Toustrup    schedule 16.09.2013
comment
Я имел в виду следующее: вы действительно пробовали скомпилировать и запустить представленный здесь код? AFAICT, это никак не могло сработать.   -  person Mark Seemann    schedule 16.09.2013
comment
Нет, это моя точка зрения. В реальной настройке IChildClass — это свойство, введенное через Unity для работы. Итак, мой вопрос: как мне заставить AutoFixture обойти это?   -  person Mads Tjørnelund Toustrup    schedule 16.09.2013
comment
Как это возможно? Свойство не может быть назначено до выполнения конструктора. Как будет выглядеть код Unity?   -  person Mark Seemann    schedule 16.09.2013
comment
Моя ставка. Я вижу вашу точку зрения. Что я не включил, так это небольшую деталь, что на самом деле Unity также создает MyClass.   -  person Mads Tjørnelund Toustrup    schedule 16.09.2013
comment
Как это имеет значение? Конструктор MyClass пытается прочитать свойство Child, которое в этот момент не инициализировано... Конечно, он выдает NullReferenceException.   -  person Mark Seemann    schedule 16.09.2013
comment
Я не пытаюсь быть умником здесь; Я бы хотел помочь, но если я что-то не упускаю, я не понимаю, как можно ожидать, что это когда-нибудь сработает. Я скопировал весь ваш код в VS и попытался создать экземпляр MyClass, и, как и ожидалось, он выдал исключение. Может быть, я просто очень скучен, но я не понимаю, как это может работать, как здесь представлено. На самом деле не имеет значения, используете ли вы new, AutoFixture или Unity...   -  person Mark Seemann    schedule 18.09.2013
comment
Позвольте мне вернуться к вам, я совсем повесился в эти дни ...   -  person Mads Tjørnelund Toustrup    schedule 19.09.2013


Ответы (1)


Приведенный выше код никогда не будет работать, потому что Initialize вызывается в Ctor. Autofixture инициализирует объект, а свойство еще не введено. Для вышеуказанного есть несколько обходных путей, но в нынешнем виде... Child всегда будет нулевым в методе Initialize.

person Ruskin    schedule 07.01.2016