Как обрабатывать исключения, возникающие в других потоках при модульном тестировании? - PullRequest
14 голосов
/ 21 мая 2009

При тестировании с помощью Visual Studio Team Test необработанные исключения в тестах отлавливаются и сообщаются в результатах. Поэтому я был немного удивлен, увидев сбой тестового хостинга (VSTestHost.exe) и показ диалогового окна сбоя системы.

При дальнейшем расследовании этот сбой был необработанным исключением, возникшим в другом потоке (точнее, это был асинхронный обратный вызов сокета). И действительно, как-то так происходит сбой процесса хостинга:

[TestMethod]
void Test()
{
    new Thread(() => { throw new Exception(); }).Start();
}

Какие советы, что мне там делать?

  • Должен ли я просто жить с этим, говоря, что любой распространяемый / проверенный код в любом случае должен быть проверен хотя бы один раз, и поэтому такие вещи, скорее всего, будут обнаружены?
  • Стоит ли пытаться установить глобальный обработчик исключений и проверять его состояние в каждом методе разрыва?
  • А может, уже есть вещи, помогающие с этим?

Ответы [ 6 ]

2 голосов
/ 01 июня 2009

Вы можете использовать обработчик Global Exception, чтобы перехватить все необработанные исключения в AppDomain:

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new EventHandler(UnhandledExceptionHandler);

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

1 голос
/ 21 мая 2009

Вы можете попробовать установить AppDomain.CurrentDomain.UnhandledException и посмотреть, работает ли это? Я не знаю, как это взаимодействует с тестовым ремнем безопасности VS

0 голосов
/ 03 июня 2009

Наличие более одного потока в ваших тестах не звучит для меня очень единично y . Есть ли что-нибудь в тестируемой логике, которая диктует, что должно быть несколько потоков? Действительно?

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

0 голосов
/ 03 июня 2009

Что я могу сказать из области C ++ (если знания можно перевести), так это то, что любое исключение, выброшенное в данном потоке, может быть перехвачено только в этом потоке . Если ваше основное приложение запускает три других потока, то вы должны отлавливать исключения из каждого (теперь 4) потока независимо. Нет способа реализовать «глобальный» обработчик исключений в многопоточном коде. Это связано с тем, как потоки (и процессы) реализованы в ОС.

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

0 голосов
/ 21 мая 2009

Пара идей:

  • Используйте BackgroundWorker для выполнения модульного теста. BackgroundWorker автоматически перехватит необработанные исключения и сообщит о них в свойстве Error RunWorkerCompletedEventArgs. Однако вам понадобится способ заблокировать поток модульного тестирования, пока BackgroundWorker не завершит работу.
  • Этот вариант не очень хорош сам по себе и может даже не подходить для ваших целей тестирования. Тем не менее я хотел упомянуть. Вы можете вернуться к тому, как обрабатывались необработанные исключения из других потоков в .NET 1.0 и 1.1, используя legacyUnhandledExceptionPolicy . До .NET 2.0 необработанные исключения из потоков незаметно игнорировались. Однако в .NET 2.0 они фактически вызывают завершение приложения. Параметр legacyUnhandledExceptionPolicy позволяет настроить поведение до версии .NET 2.0.
0 голосов
/ 21 мая 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...