Как написать интеграционные и системные тесты в Asp.net MVC - PullRequest
9 голосов
/ 30 сентября 2010

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

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

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

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

Ответы [ 3 ]

5 голосов
/ 30 сентября 2010

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

Системным тестом для меня будет функциональное тестирование (еще один уровень тестирования с использованием чего-то вроде fit) или пользовательское тестирование с помощью такого инструмента, как testcomplete или telerik QA tool.

НТН.

2 голосов
/ 30 сентября 2010

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

Часть проблемы заключается в том, что интеграционные тесты более высокого уровня слишком быстро становятся слишком сложными.Это характер проблемы, поэтому я предпочитаю убедиться, что все отдельные части работают должным образом, с помощью модульных тестов и целевых интеграционных тестов в зависимости от участвующего класса.

Учитывая вышесказанное, вам нужно только убедиться, что отдельные части правильно подключены, поэтому я использую полные системные тесты для этого.Это имеет лучший эффект, если код следует за SOLID и DRY.

2 голосов
/ 30 сентября 2010

Интеграционные тесты, в которых не используется пользовательский интерфейс, можно по-прежнему писать в NUnit, xUnit и т. Д.

В частности, для ASP.NET MVC (или любого веб-приложения) можно использовать WatiN или Selenium для написания системных / интеграционных тестов с использованием пользовательского интерфейса.

Возможно, вы также захотите посмотреть TST для модульного тестирования T-SQL и SpecFlow , если вам интересно узнать о BDD в .NET.

Примечание. Я написал это до того, как вопрос был обновлен с помощью кода и описания конкретной ситуации.Это больше не решает вопрос, но, надеюсь, все равно будет интересно / полезно для кого-то.

...