简体   繁体   English

单元测试通过调试,但在运行时挂起

[英]Unit-test passes in Debug, but hangs when Run

I have an odd problem. 我有一个奇怪的问题。 I have a unit test that keeps getting stuck in Run Mode. 我有一个单元测试,它总是卡在“运行模式”下。 When I run the same test in Debug, with no breakpoints, the test passes every time. 当我在Debug中运行相同的测试且没有断点时,该测试每次都会通过。

Basically, it is a socket connection test. 基本上,这是套接字连接测试。 I first disconnect a socket, and then try to reconnect, and I am trying to check if the reconnection was successful. 我首先断开套接字,然后尝试重新连接,然后尝试检查重新连接是否成功。

Somewhere in the connect code, I check if there was a socket exception. 在连接代码中的某个地方,我检查是否有套接字异常。 When this happens, the user is presented with some choices in a dialog, while the connection code hangs via an AutoResetEvent, waiting for a decision. 发生这种情况时,会在对话框中为用户提供一些选择,而连接代码会通过AutoResetEvent挂起,等待决策。

It is this AutoResetEvent that hangs the system. 正是这个AutoResetEvent挂起了系统。 It must be provided by code in the unit test. 它必须由单元测试中的代码提供。 But my question is, how come this passes in Debug mode? 但是我的问题是,这如何在调试模式下通过? Is there something special about debug mode whereby AutoResetEvents are automatically set by Visual Studio? 通过Visual Studio自动设置AutoResetEvents的调试模式有什么特别之处吗?

EDIT 编辑

It was indeed a race condition. 确实,这是比赛条件。 I added a delay in the code after my disconnect code, and it works now. 我在断开连接代码之后在代码中添加了一个延迟,现在它可以工作了。 But it still strikes me as odd that there is a race condition to begin with. 但这仍然让我感到奇怪,因为这里有一个比赛条件。 Let me elaborate by pasting some of the code. 让我通过粘贴一些代码来详细说明。

This is the test code: 这是测试代码:

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

The reason this strikes me, is that I am waiting for a return on the diconnect code, before calling the connect code. 令我震惊的原因是,我在调用连接代码之前正在等待diconnect代码的返回。 The last part of the disconnect code looks like this: 断开连接代码的最后一部分如下所示:

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

Is it be because Socket.Shutdown(), and/or Socket.Close() methods run it threads? 是因为Socket.Shutdown()和/或Socket.Close()方法在线程上运行它吗? Thus, even though I am returning a value from my disconnect code, the socket isn't actually truly disconnected? 因此,即使我从断开连接代码返回一个值,套接字实际上并没有真正断开连接?

It sounds like a race condition. 听起来像是比赛条件。 Debug code usually runs a lot of extra stuff 'under the hood', and that difference in timing is probably throwing your tests off. 调试代码通常在“幕后”运行许多额外的东西,并且时间上的差异可能会导致测试失败。

Of course without seeing code, we really can't help you very much. 当然,如果没有看到代码,我们真的无法为您提供很大帮助。

Most likely because of a threading race. 最有可能是由于线程竞赛。 They are very sensitive to timing and the timing in the Debug build will be different. 它们对时序非常敏感,并且Debug版本中的时序会有所不同。 You can use a tool like CHESS to exercise bugs like that. 您可以使用CHESS之类的工具来执行此类错误。

But use Tools + Attach to Process first. 但是请先使用工具+附加到流程。 Debug + Break All, Debug + Windows + Threads and look at the thread call stacks. 调试+全部破坏,调试+ Windows +线程,然后查看线程调用堆栈。 You might be able to see the cause of the race or deadlock. 您也许可以查看比赛或僵局的原因。

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

This test is telling you that your code is not properly isolated from the socket library you are using. 该测试告诉您您的代码未与所使用的套接字库正确隔离。 The code that you are testing should not have to depend upon certain artifacts with-in this library. 您正在测试的代码不必依赖于此库中的某些工件。 You need to add an abstraction between the socket library that takes the artifacts into acoount. 您需要在套接字库之间添加一个抽象,以将工件放入acoount中。

The reason I say this is, is what if the socket actually disconnects 123,251 times < 100 mSecs, but the 123,252nd time disconnecting takes 101 mSecs. 我说这的原因是,如果套接字实际上断开123,251次<100 mSecs,但是第123,252次断开需要101 mSecs。

I would highly recommend that almost all your unit-testing code not use threading. 我强烈建议几乎所有的单元测试代码都不要使用线程。 I look at threading calls of any type in my unit tests as a code smell. 我将单元测试中任何类型的线程调用视为代码气味。 usually where I want to see threading issues is at the integration level. 通常,我希望看到线程问题的地方是集成级别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM