单元测试在Debug中传递,但在Run时挂起

时间:2010-07-19 14:49:55

标签: visual-studio-2010 unit-testing debugging autoresetevent

我有一个奇怪的问题。我有一个单元测试,一直卡在运行模式。当我在Debug中运行相同的测试时,没有断点,每次都会通过测试。

基本上,它是套接字连接测试。我首先断开插座,然后尝试重新连接,我试图检查重新连接是否成功。

在连接代码中的某处,我检查是否存在套接字异常。发生这种情况时,会在对话框中向用户显示一些选项,而连接代码会通过AutoResetEvent挂起,等待决定。

正是这个AutoResetEvent挂起了系统。它必须由单元测试中的代码提供。 但我的问题是,为什么这会在调试模式下通过?调试模式有什么特别之处,因为Visual Studio会自动设置AutoResetEvents吗?

修改

这确实是一场竞争。我在断开连接代码后添加了代码延迟,现在可以正常工作了。但令人感到奇怪的是,有一个竞争条件开始。让我通过粘贴一些代码来详细说明。

这是测试代码:

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());

这让我感到震惊的原因是,在调用连接代码之前,我正在等待返回diconnect代码。断开代码的最后一部分如下所示:

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

是因为Socket.Shutdown()和/或Socket.Close()方法运行它的线程吗?因此,即使我从断开代码返回一个值,套接字实际上并没有真正断开连接?

4 个答案:

答案 0 :(得分:2)

这听起来像是竞争条件。调试代码通常会在“引擎盖下”运行很多额外的东西,而时间差异可能会导致你的测试失败。

当然没有看到代码,我们真的无法帮助你。

答案 1 :(得分:2)

很可能是因为线程竞赛。它们对时序非常敏感,Debug构建中的时序也不同。您可以使用像CHESS这样的工具来修复这样的错误。

但首先使用Tools + Attach to Process。 Debug + Break All,Debug + Windows + Threads并查看线程调用堆栈。您可能能够看到种族或死锁的原因。

答案 2 :(得分:1)

有一个类似的问题,我比较了两个日期,并期望一个日期一个接一个,但因为它执行得那么快,他们收到了相同的时间戳。

答案 3 :(得分:0)

此测试告诉您,您的代码未与正在使用的套接字库正确隔离。您正在测试的代码不应该依赖于此库中的某些工件。您需要在将工件置于acoount的套接字库之间添加抽象。

我说这个的原因是,如果套接字实际断开连接123,251次&lt; 100 mSecs,但123,252次断开连接需要101 mSecs。

我强烈建议您几乎所有的单元测试代码都不使用线程。我在单元测试中看到任何类型的线程调用作为代码气味。通常我希望看到线程问题处于集成级别。