Подтвердить что ты не робот

Правильный способ для Mock объектов репозитория для модульных тестов с использованием Moq и Unity

В моей работе мы используем Moq для издевательств и Unity для контейнера IOC. Я новичок в этом и не имею много ресурсов на работе, чтобы помочь мне в определении лучших практик, которые я должен использовать.

В настоящее время у меня есть группа интерфейсов репозитория (Ex: IRepository1, IRepository2... IRepository4), которые необходимо выполнить конкретному процессу для выполнения своей работы.

В фактическом коде я могу определить все объекты IRepository, используя контейнер IOC и используя метод RegisterType().

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

Я думал, что могу просто зарегистрировать новый экземпляр контейнера Unity IOC и вызвать RegisterInstance в контейнере для каждого макета, проходящего в значение Mock.Object для каждого из них. Я пытаюсь сделать этот процесс регистрации многократно используемым, поэтому мне не нужно продолжать делать одно и то же снова и снова с каждым unit test, если только unit test не требует, чтобы некоторые конкретные данные возвращались из репозитория. Вот где проблема... Какова наилучшая практика для настройки ожидаемых значений в издеваемом репозитории? Похоже, если я просто вызову RegisterType в контейнере Unity, я бы потерял ссылку на фактический объект Mock и не смог бы переопределить поведение.

4b9b3361

Ответ 1

Единичные тесты не должны использовать контейнер вообще. Инъекция зависимостей (DI) происходит в два этапа:

  • Используйте шаблоны DI для встраивания зависимостей в потребителей. Для этого вам не нужен контейнер.
  • В приложении Root of Composition используйте контейнер DI (или Bad Man DI) для соединения всех компонентов.

Как вообще не использовать какой-либо контейнер DI для модульного тестирования

В качестве примера рассмотрим класс, который использует IRepository1. Используя шаблон Конструктор Injection, мы можем сделать зависимость инвариантом класса.

public class SomeClass
{
    private readonly IRepository1 repository;

    public SomeClass(IRepository1 repository)
    {
        if (repository == null)
        {
            throw new ArgumentNullException("repository");
        }

        this.repository = repository;
    }

    // More members...
}

Обратите внимание, что ключевое слово readonly в сочетании с предложением Guard гарантирует, что поле repository не равно null, если экземпляр был успешно создан.

Вам не нужен контейнер для создания нового экземпляра MyClass. Вы можете сделать это непосредственно из unit test с помощью Moq или другого тестового двойника:

[TestMethod]
public void Test6()
{
    var repStub = new Mock<IRepository1>();
    var sut = new SomeClass(repStub.Object);
    // The rest of the test...
}

Смотрите здесь для получения дополнительной информации...

Как использовать Unity для модульного тестирования

Однако, если вы абсолютно должны использовать Unity в своих тестах, вы можете создать контейнер и использовать метод RegisterInstance:

[TestMethod]
public void Test7()
{
    var repMock = new Mock<IRepository1>();

    var container = new UnityContainer();
    container.RegisterInstance<IRepository1>(repMock.Object);

    var sut = container.Resolve<SomeClass>();
    // The rest of the test...
}