呼び出しているオブジェクトからイベントを受け取ることを期待するテストを書いています。具体的には、(オープン ソースの Granados プロジェクトを使用して) SSH 経由で 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;
}
}