我正在编写一个期望从它正在调用的对象接收事件的测试。具体来说,我正在调用一个通过 SSH(使用开源 Granados 项目)连接到 AIX 机器的对象,然后断开连接,并且我想确保收到在断开连接期间引发的 OnConnectionClosed 事件。这听起来很简单,过去我写过很多这样的测试,但是这次发生了一些我认为与线程有关的奇怪行为。
基本上,我调用的对象是在与我调用它的线程不同的线程上引发“OnConnectionClosed”事件。我看到的是,当我通过从 UI 中选择“调试测试”来运行测试时,它通过了,但是如果我选择“运行测试”,它就会失败(即使在调试运行期间没有设置断点)。我做了一些谷歌搜索,发现这篇文章似乎表明默认情况下 MSTest 主机以单线程模式运行,但配置更改可以使其以多线程模式运行。这听起来像是从逻辑上解决了我的问题,但当然,它没有。
我遇到的其他一些帖子也让我认为 MSTest 根本没有监视后台线程(因此它们引发的事件没有被“听到”)。这也是有道理的,因为它似乎在调试模式下工作,而且上面的修复似乎应该在逻辑上解决这个问题,那么我对它为什么不起作用感到困惑。我可能只是没有正确处理线程,尽管如果是这种情况,我希望在调试模式下这仍然是一个问题。
有没有其他人试图以类似的方式测试一些东西?如果是这样,您是否遇到过类似的问题?如果是这样,你是如何解决它们的?
我在下面粘贴了相关的单元测试代码(出于安全原因,我删除了连接信息)。
[TestClass]
public class SSHReaderTests
{
private bool received = false;
private delegate bool SimpleFunc();
[TestInitialize]
public void MyTestInitialize()
{
received = false;
}
[TestMethod]
public void Should_raise_OnReaderConnectionClosed_event_after_successful_connection_is_disconnected()
{
IReader reader = new SSHReader();
reader.OnReaderConnectionClosed += delegate
{
received = true;
};
reader.Connect("*****", "*****", "*****");
//Assert.IsTrue(reader.IsConnected);
reader.Disconnect();
//Assert.IsFalse(reader.IsConnected);
Assert.IsTrue(WaitUntilTrue(delegate {
return received; }, 30000, 1000));
}
private static bool WaitUntilTrue(SimpleFunc func, int timeoutInMillis, int timeBetweenChecksInMillis)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
while(stopwatch.ElapsedMilliseconds < timeoutInMillis)
{
if (func())
return true;
Thread.Sleep(timeBetweenChecksInMillis);
}
return false;
}
}