Куда двигать конструирование одноразовых зависимостей для улучшения тестируемости? - PullRequest
3 голосов
/ 30 декабря 2011

В своих модульных тестах я использую такие вещи, как AssemblyInitialize, ClassInitialize и TestInitialize для настройки моих тестов. В AssemblyInitialize я инициализирую некоторые одноэлементные фабрики для создания сервисов, единицы работы и репозиториев (все через Unity / Dependency Injection). В моем TestInitialize я очищаю состояние, в котором они должны убедиться, что каждый тест может выполняться независимо.

Через Stackoverflow Я пришел к следующим статьям: Написание тестируемого кода и Как думать о «новом» операторе в отношении модульного тестирования . Я должен сказать, что они изменили то, как я думаю о некотором коде, который я написал, но мой ум все еще гудит.

Например, возьмите следующий код:

public class MyPresenter : BasePresenter<IMyView>
{
    public MyPresenter(IMyView view) 
        : base(view)
    {
    }

    public void PrepareView()
    {
        using (IMyService service = ServiceFactory.Instance.CreateService<IMyService>())
        {
            View.Data = service.GetData();
        }
    }
}

Который используется на странице aspx следующим образом:

Presenter = new MyPresenter(this);
if (!IsPostback)
{
    presenter.PrepareView();
}

Как мне изменить этот тип вида с учетом предыдущих статей? Должен ли я передать экземпляр службы в метод PrepareView? Но тогда моя страница ASPX должна знать об услугах, фабриках и прочем, и утилизировать службу после ее использования.

Что мне делать с моей фабрикой в ​​Синглтоне? Сделать это свойством класса и внедрить его через Unity?

Ответы [ 2 ]

3 голосов
/ 30 декабря 2011

Я нашел этот вид разрешения зависимостей не элегантным. Взгляните на способ Ninject связать зависимости или внедрить их.

Вы можете увидеть разницу, Service Locator является антипаттерном, читая этот блог также разъясняет основные цели и методы внедрения зависимостей в .NET

0 голосов
/ 30 декабря 2011

вижу только два варианта:

  1. Внедрение зависимости сервиса напрямую (но вы упомянули, что не любите разрешение сервиса на уровне ASPX)
  2. Передайте абстрагированный DI-контейнер презентатора, а затем разрешите зависимость в Presenter (но вы упомянули, что это тоже не нравится, поскольку API будет неясным)

Я бы предпочел второй вариант, чтобы каждый докладчик знал, какие зависимости ему нужны, поскольку вы используете DI-контейнер (Unity), почему бы не избавиться от фабрики синглтонов и просто зарегистрировать все фабрики в Unity, чтобы вы могли получить к ним доступ там, где вам это нужно и модульное тестирование кода без каких-либо головной боли (так как меньше одиночных тонов). Так что просто передайте DI-контейнер каждому докладчику (учитывая, что вы отметили, что не хотите хранить все это на странице ASPX) в качестве второго параметра, а затем разрешите все необходимые службы для конкретного докладчика:

class Presenter
{
    public Presenter(IView, IDiContainerAbstraction container)
    ...
}

Presenter = new MyPresenter(this, unityContainer); 
public void PrepareView()      
{  
    using (IMyService service = this.unityContainer.Resolve<IMyService>())
    {
        View.Data = service.GetData();  
    }
}

Итак:

  • Нет синглетных зависимостей, что делает возможным модульное тестирование
  • Поскольку DI-контейнер абстрагируется от интерфейса, вы можете передать его в Mock презентатора во время модульного тестирования
...