2

我有一个奇怪的问题。我有一个单元测试一直卡在运行模式。当我在 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());

这让我印象深刻的原因是,在调用连接代码之前,我正在等待断开连接代码的返回。断开连接代码的最后一部分如下所示:

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

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

4

4 回答 4

2

这听起来像是一个竞赛条件。调试代码通常会在“幕后”运行很多额外的东西,而时间上的差异可能会导致你的测试失败。

当然没有看到代码,我们真的帮不了你很多。

于 2010-07-19T14:54:51.800 回答
2

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

但首先使用工具 + 附加到进程。Debug + Break All,Debug + Windows + Threads 并查看线程调用堆栈。您可能能够看到比赛或僵局的原因。

于 2010-07-19T14:56:38.963 回答
1

曾经有一个类似的问题,我比较了两个日期,并期望一个日期后一个日期,但由于执行速度如此之快,他们收到了相同的时间戳。

于 2010-07-19T15:03:22.057 回答
0

这个测试告诉你你的代码没有与你正在使用的套接字库正确隔离。您正在测试的代码不应该依赖于这个库中的某些工件。您需要在将工件纳入帐户的套接字库之间添加一个抽象。

我这么说的原因是,如果套接字实际断开连接 123,251 次 < 100 毫秒,但第 123,252 次断开连接需要 101 毫秒。

我强烈建议您几乎所有的单元测试代码都不要使用线程。我将单元测试中任何类型的线程调用视为代码异味。通常我想看到线程问题的地方是集成级别。

于 2010-07-19T17:09:28.280 回答