В моем приложении ASP.Net MVC я использую IoC для облегчения модульного тестирования. Структура моего приложения - тип структуры Controller -> Service Class -> Repository
. Для проведения модульного тестирования у меня есть класс InMemoryRepository
, который наследует мой IRepository
, который вместо выхода в базу данных использует внутренний член List<T>
. Когда я строю свои модульные тесты, я просто передаю экземпляр внутреннего репозитория вместо моего репозитория EF.Должен ли я использовать макет объектов при модульном тестировании?
Мои классы обслуживания извлекают объекты из репозитория через интерфейс AsQueryable
, который реализуются моими классами репозитория, что позволяет мне использовать Linq в моих классах обслуживания без класса обслуживания, все еще абстрагируя уровень доступа к данным. На практике это, похоже, работает хорошо.
Проблема, которую я вижу, заключается в том, что каждый раз, когда я смотрю «Unit Testing», они используют макетные объекты вместо внутреннего метода, который я вижу. По значению лица это имеет смысл, потому что, если мой InMemoryRepository
терпит неудачу, мои тесты InMemoryRepository
не удастся, но эта ошибка также будет каскадироваться в мои классы обслуживания и контроллеры. Более реалистично меня больше беспокоят неудачи в моих классах обслуживания, влияющие на тесты модулей контроллера.
Мой метод также требует, чтобы я делал больше настроек для каждого модульного теста, и по мере усложнения ситуации (например, я реализую авторизацию в классах услуг) настройка становится намного сложнее, потому что тогда мне нужно убедиться, что каждая единица тест разрешает его с помощью классов обслуживания правильно, поэтому основной аспект этого модульного теста не прерывается. Я могу ясно видеть, как макеты могут помочь в этом отношении.
Однако я не могу понять, как решить эту проблему полностью с помощью mocks и все еще иметь действующие тесты. Например, один из моих модульных тестов: если я вызываю _service.GetDocumentById(5)
, он получает правильный документ из репозитория. Единственный способ - это действительный модульный тест (насколько я понимаю), если у меня есть 2 или 3 документа, и мой метод GetdocumentById()
правильно извлекает тот, у которого есть идентификатор 5.
Как мне получить mockinged repository с вызовом AsQueryable
, и как бы я удостоверился, что я не замаскирую какие-либо проблемы, которые я создаю с помощью своих операторов Linq, путем hardcoding операторов return при настройке издевающегося репозитория? Лучше ли проводить тестирование модуля класса обслуживания с помощью InMemoryRepository
, но изменить тесты моего контроллера, чтобы использовать издеваемые объекты обслуживания?
Edit: После перехода моей структуры я снова вспомнил осложнение, которое предотвращает насмешливым в единичных тестах контроллера, так как я забыл мою структура является немного более сложной, чем я сказал.
A Repository
- это хранилище данных для одного типа объектов, поэтому, если моему классу службы документов нужны объекты документа, он создает IRepository<Document>
.
Контроллеры передаются IRepositoryFactory
. IRepositoryFactory
- это класс, который, как предполагается, упрощает создание репозиториев без непосредственного обращения к репозиторию в контроллер или если диспетчер беспокоится о том, какие классы услуг требуют, какие репозитории. У меня есть InMemoryRepositoryFactory
, который дает классы обслуживания InMemoryRepository<Entity>
экземпляров, и эта же идея касается моего EFRepositoryFactory
.
В конструкторах контроллера объекты частного обслуживания создаются путем передачи в объекте IRepositoryFactory
, который передается в этот контроллер.
Так, например
public class DocumentController : Controller
{
private DocumentService _documentService;
public DocumentController(IRepositoryFactory factory)
{
_documentService = new DocumentService(factory);
}
...
}
Я не могу видеть, как издеваются мой уровень сервиса с этой архитектурой, так что мои контроллеры протестированы и не интеграция испытания. У меня могла быть плохая архитектура для модульного тестирования, но я не уверен, как лучше решить проблемы, из-за которых я хочу создать фабрику репозитория в первую очередь.
«Лучше ли проводить тестирование единицы измерения класса обслуживания с помощью« InMemoryRepository », но изменить тесты модуля-контроллера, чтобы использовать насмешливые объекты обслуживания?» Да, точно. –
Я только что обновил вопрос, чтобы добавить более подробную информацию о том, почему издевающийся уровень сервиса при тестировании контроллеров мне не кажется очевидным. – KallDrexx