Юнит-тест проходит в отладке, но зависает при запуске

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

По сути, это тест подключения к сокету. Сначала я отключаю сокет, а затем пытаюсь снова подключиться, и я пытаюсь проверить, было ли переподключение успешным.

Где-то в коде подключения я проверяю, было ли исключение сокета. Когда это происходит, пользователю предоставляется несколько вариантов выбора в диалоговом окне, в то время как код подключения зависает через AutoResetEvent, ожидая решения.

Именно этот AutoResetEvent и вешает систему. Он должен быть предоставлен кодом в модульном тесте. Но мой вопрос в том, как это происходит в режиме отладки? Есть ли что-то особенное в режиме отладки, при котором события AutoResetEvents автоматически устанавливаются Visual Studio?

ИЗМЕНИТЬ

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

Это тестовый код:

MySystem.FindEquipment(new List<string>(1) { "192.1.1.243:28000" });
MySystem.ConstructSystem();
MySystem.IsConstructedFlag.WaitOne();
Assert.AreEqual(1, MySystem.CommunicationController.HardwareIPList.Count);

PFFrame frame1 = MySystem.Frames["0.x.x"];

Assert.IsTrue(frame1.Disconnect());
Thread.Sleep(100);
Assert.IsTrue(frame1.Connect());

Причина, по которой это поражает меня, заключается в том, что я жду возврата кода отключения, прежде чем вызывать код подключения. Последняя часть кода отключения выглядит так:

lclSocket.Shutdown(SocketShutdown.Both);
lclSocket.Close();
OnSocketDisconnected(new PFSocketConnectionEventArgs(ipEp));
return true;

Это потому, что методы Socket.Shutdown() и/или Socket.Close() запускают потоки? Таким образом, даже если я возвращаю значение из моего кода отключения, сокет на самом деле не отключен?


person sbenderli    schedule 19.07.2010    source источник
comment
Я никогда не использовал .NET Socket API, поэтому здесь я мало чем могу вам помочь. Я предполагаю, что lclSocket является экземпляром класса System.Net.Sockets.Socket? Просто взглянув на документы, я вижу, что существуют различные асинхронные методы, когда вы работаете в многопоточной среде. Вероятно, вам следует отменить изменения кода, закомментировав код, пока ваш код не заработает в отладке и выпуске. Затем внимательно просмотрите документы, убедившись, что вы использовали правильные методы. Тем временем утверждать все. Затем постепенно добавляйте небольшие фрагменты кода по одному, пока не сузите ошибку.   -  person C Johnson    schedule 19.07.2010


Ответы (4)


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

Конечно, не видя кода, мы мало чем можем вам помочь.

person C Johnson    schedule 19.07.2010
comment
Это действительно было состояние гонки... но у меня остался еще один вопрос, пожалуйста, посмотрите, как я отредактирую. - person sbenderli; 19.07.2010

Скорее всего из-за гонки потоков. Они очень чувствительны к времени, и время в отладочной сборке будет другим. Вы можете использовать такой инструмент, как CHESS, чтобы тренировать подобные ошибки.

Но сначала используйте Tools + Attach to Process. Debug + Break All, Debug + Windows + Threads и посмотрите на стеки вызовов потоков. Возможно, вы сможете увидеть причину гонки или тупика.

person Hans Passant    schedule 19.07.2010

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

person bertolami    schedule 19.07.2010

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

Причина, по которой я говорю это, заключается в том, что, если сокет фактически отключается 123 251 раз ‹ 100 мсек, но 123 252-й раз отключение занимает 101 мсек.

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

person Gutzofter    schedule 19.07.2010
comment
Я знаю, я хотел добавить Thread.Sleep, чтобы убедиться, что я пытался восстановить соединение после полного отключения. В моем коде отключения я сначала вызываю Shutdown, а затем Close. Однако я пока не знаю, как проверить, полностью ли отключен Socket и готов ли он к новой попытке подключения. Любые идеи? - person sbenderli; 19.07.2010
comment
Вы не намерены тестировать Socket.Shutdown или Socket.Close, верно? Так что уберите их и просто проверьте, что ваш код вызывает их в соответствующем порядке. - person TamaMcGlinn; 26.03.2018