かなり長い間、
「ファイナライザコードをテストする方法(c#)」という投稿を公開しました。この投稿では、ファイナライザに実装されたコードをテストした経験を共有しました。 テストが落ちる前に一年も経っていませんでした。 カットの下の詳細。
つまり、AppDomainを使用したファイナライザーコードのテストメソッドについて説明しました。
[Test] public void TestTemporaryFile_without_Dispose() { const string DOMAIN_NAME = "testDomain"; const string FILENAME_KEY = "fileName"; string testRoot = Directory.GetCurrentDirectory(); AppDomainSetup info = new AppDomainSetup { ApplicationBase = testRoot }; AppDomain testDomain = AppDomain.CreateDomain(DOMAIN_NAME, null, info); testDomain.DoCallBack(delegate { MyTemporaryFile temporaryFile = new MyTemporaryFile(); Assert.IsTrue(File.Exists(temporaryFile.FileName)); AppDomain.CurrentDomain.SetData(FILENAME_KEY, temporaryFile.FileName); }); string createdTemporaryFileName = (string)testDomain.GetData(FILENAME_KEY); Assert.IsTrue(File.Exists(createdTemporaryFileName)); AppDomain.Unload(testDomain);
予言がメモに書いたように:
3.ほとんどの場合、このテストの実装にもあらゆる種類の微妙なポイントがありますが、長年の実践でこのテストの誤検出が記録されたことはありません。
この投稿が公開されてから1年も経たないうちに、テストはまだ失敗しました。
Assert.IsTrue(File.Exists(createdTemporaryFileName));
この行は、オブジェクトがもう存在しないにもかかわらず、ドメインで作成されたファイルがまだ存在することを確認します。
最初は信じさえしませんでした。もう一度始めました。 次に、
Repeat属性を使用してテストを開始しました。
[Test] [Repeat(1000)] public void TestTemporaryFile_without_Dispose() { ... }
そしてテストは落ちました。
彼は実験を行い、テストが私のコンピューター上で1000スタート(0.7%-0.8%)で7-8回クラッシュすることを受け取りました。
私が正しく理解していれば、オブジェクトのファイナライザーが非常にすばやく呼び出されることがありますが、このテストではファイルがまだ存在することを確認する時間がありません。
ファイルの存在のチェックを中止する必要がありました。テストでは、アプリケーションドメイン(AppDomain.Unload)をアンロードした後、ファイルが存在しないことを確認します。
さて、さらに進んだ場合、このファイル(標準の一時ファイル)はオペレーティングシステムによって別の(並列)テストから、または一般に別のプログラムによって再作成できるため、ファイルがないことを確認するとこのテストがクラッシュすることが予想されます。
何が間違っていますか?
私は問題があります、プロセスは一時ファイルを作成および破壊します、プロセスは長い間生きることができます、作成された一時ファイルを削除するのが悪い場合、それらは物理的に不足し、オペレーティングシステムから一時ファイルを取得する次の試みは失敗します。
だから、私はそのようなオプションを見ます:
-時々このテストの偶発的な落下を確認してください。
-テストのスコア(ハンドルで数回確認);
-標準の一時ファイルを使用しないでください。