Мое приложение
У меня есть дизайн приложения, который выглядит следующим образом:
- уровень веб-приложения - приложение asp.net MVC с контроллерами и представлениями, которые используют POCO и службы вызовов
- уровень обслуживания - бизнес-процессы, использующие POCO и репозитории вызовов
- уровень данных - репозитории, которые используют POCO и взаимодействуют с моделью в форме модели EF, которая является частью этого же уровня
- Уровень POCO - определяет все классы, которые используются для взаимодействия между этими уровнями
Таким образом, мой уровень данных полностью прозрачен для реализации модели данных, поскольку верхний уровень вообще не использует объекты данных.
Тестирование
Насколько я понимаю, юнит, интеграция и тестирование системы (по отношению к Asp.net MVC) таковы:
- модульное тестирование - это легко. Смоделируйте разъединенные объекты и внедрите их в свой юнит-тест, чтобы протестированный юнит использовал их
- интеграционное тестирование - следует создать группу производственных функциональных блоков и смоделировать остальное: так, написание интеграционных тестов, которые тестировали бы интеграцию контроллера, сервиса и репозитория без фактического использования производственной базы данных
- системное тестирование - запускать тесты на всех слоях без каких-либо насмешек, что означает, что я должен использовать производственную (тестовую) базу данных
Проблема
Я легко вижу, как писать модульные тесты, а также системные тесты, но я не знаю, как писать интеграционные тесты? Возможно, мой взгляд на них полностью искажен, и я их совсем не понимаю.
Как написать интеграционные и системные тесты для приложения Asp.net MVC?
Или любое приложение .net по этому вопросу?
Код, помогающий объяснить проблему
Предположим, у меня есть такие классы, как:
TaskController
звонки на TaskService
TaskService
звонки на TaskRepository
TaskRepository
внутренне манипулировать данными EF
Итак, вот мои (сокращенно) классы:
public class TaskController
{
private ITaskService service;
// injection constructor
public TaskController(ITaskService service)
{
this.service = service;
}
// default constructor
public TaskController() : this(new TaskService()) {}
public ActionResult GetTasks()
{
return View(this.service.GetTasks());
}
...
}
public class TaskService : ITaskService
{
private ITaskRepository repository;
// injection constructor
public TaskService(ITaskRepository repository)
{
this.repository = repository;
}
// default constructor
public TaskService() : this(new TaskRepository()) {}
public IList<Task> GetTasks()
{
return this.repository.GetTasks();
}
...
}
public class TaskRepository : ITaskRepository
{
public IList<Task> GetTasks()
{
// code that gets tasks from EF and converts to Task POCOs
}
...
}
Модульный тест прост и будет выглядеть так:
public void UnitTest()
{
var mock = new Mock<ITaskService>();
// other code that mocks the service
TaskController controller = new TaskController(mock.Object);
// do the test
}
Но когда дело доходит до интеграционного теста, как мне высмеивать только определенные части интеграции.
public void IntegrationTest()
{
// no mocking at all
TaskController = new TaskController();
// do some testing
}
Прежде всего, я не могу просто смоделировать базу данных здесь? Я мог бы смоделировать репозиторий и иметь реальный сервис и контроллер, хотя ...