Как писать интеграционные и системные тесты в Asp.net MVC

Мое приложение

У меня есть дизайн приложения, который выглядит следующим образом:

  • уровень веб-приложения - 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
}

Во-первых, не могу же я просто поиздеваться над базой данных? Я мог бы сымитировать репозиторий и иметь реальный сервис и контроллер, хотя...

9
задан Robert Koritnik 30 September 2010 в 13:07
поделиться