Как смоделировать события, вызывающие исключения, для тестирования блоков try / catch?

14

Я понимаю, как работают исключения и как их перехватывать и обрабатывать в C #, но как я могу имитировать события, которые могут вызвать исключение, чтобы убедиться, что оно перехвачено правильно? Например, возможно ли запустить приложение в некой тестовой среде, где можно моделировать проблемы с сетью, проблемы с базой данных и т. Д.? Исключения по своей природе кажутся трудно воспроизводимыми, что затрудняет обеспечение того, чтобы ваш код справился с ними.

Хотя я в основном разрабатываю с использованием C # /. NET / Visual Studio, ответы или ресурсы, относящиеся к другим языкам, могут быть полезны.

Пирс Майерс
источник
Еще одно возможное решение описано в этой статье MSDN: тестирование на внедрение с помощью TestApi
Giorgi

Ответы:

13

1) Если вы следовали модели внедрения зависимостей, вы могли бы заменить реальные реализации определенных частей на макеты, которые будут генерировать исключения по мере необходимости. Это, однако, потребовало бы от вас изначально разработать свое приложение особым образом или полностью переработать его.

Подобно:

public class SqlUsersRepository : IUsersRepository
{
    public void RegisterNewUser (User newUser)
    {
        throw new SqlException ("Connection timeout");
    }
}

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

2) Другой подход - заменить определенные вызовы методов вашими пользовательскими обертками.

Вместо того:

FileStream fs = File.OpenRead (path);

ты используешь:

FileStream fs = File.OpenRead_Test (path);

предоставив собственный метод расширения (просто быстрая идея):

public static FileStream OpenRead_Test (this System.IO.File file, string path)
{
    throw new FileNotFoundException ();
}

источник
3

Вам нужно посмотреть на насмешливые рамки.

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

Затем вы настраиваете тест, который при вызове просто вызывает желаемое исключение:

public void Test1()
{
    throw new NullArgumentException();
}

Ваш тест проходит, когда ваш код обрабатывает это правильно.

ChrisF
источник
3

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

Если вы не хотите перепроектировать свое приложение, чтобы оно подходило для среды тестирования, тогда вам действительно нужен хост или среда, сфальсифицированная на наличие ошибок. Существует много способов симуляции медленной работы сети в случае сбоя (даже в инструментах тестирования Microsoft есть немного этого в области веб-тестирования). Я добился наибольшего успеха в размещении машин за маршрутизатором, который может быть подделан для изменения симуляции в координации с набором базы данных для создания ошибок и сценариев для изменения ошибок, которые выдает база данных.

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

Билл
источник
Согласовано - в некоторых случаях вы не можете позволить себе накладные расходы, например, из-за внедрения зависимостей в ваш код выпуска. Не повседневная проблема, но это может случиться.
Steve314